import most of e2fsprogs 1.38 updates
[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  *      @m      multiply-claimed
3716  *      @n      invalid
3717  *      @o      orphaned
3718  *      @p      problem in
3719  *      @r      root inode
3720  *      @s      should be
3721  *      @S      superblock
3722  *      @u      unattached
3723  *      @v      device
3724  *      @z      zero-length
3725  */
3726
3727
3728 /*
3729  * This structure defines the abbreviations used by the text strings
3730  * below.  The first character in the string is the index letter.  An
3731  * abbreviation of the form '@<i>' is expanded by looking up the index
3732  * letter <i> in the table below.
3733  */
3734 static const char * const abbrevs[] = {
3735         N_("aextended attribute"),
3736         N_("Aerror allocating"),
3737         N_("bblock"),
3738         N_("Bbitmap"),
3739         N_("ccompress"),
3740         N_("Cconflicts with some other fs @b"),
3741         N_("iinode"),
3742         N_("Iillegal"),
3743         N_("jjournal"),
3744         N_("Ddeleted"),
3745         N_("ddirectory"),
3746         N_("eentry"),
3747         N_("E@e '%Dn' in %p (%i)"),
3748         N_("ffilesystem"),
3749         N_("Ffor @i %i (%Q) is"),
3750         N_("ggroup"),
3751         N_("hHTREE @d @i"),
3752         N_("llost+found"),
3753         N_("Lis a link"),
3754     N_("mmultiply-claimed"),
3755     N_("ninvalid"),
3756         N_("oorphaned"),
3757         N_("pproblem in"),
3758         N_("rroot @i"),
3759         N_("sshould be"),
3760         N_("Ssuper@b"),
3761         N_("uunattached"),
3762         N_("vdevice"),
3763         N_("zzero-length"),
3764         "@@",
3765         0
3766         };
3767
3768 /*
3769  * Give more user friendly names to the "special" inodes.
3770  */
3771 #define num_special_inodes      11
3772 static const char * const special_inode_name[] =
3773 {
3774         N_("<The NULL inode>"),                 /* 0 */
3775         N_("<The bad blocks inode>"),           /* 1 */
3776         "/",                                    /* 2 */
3777         N_("<The ACL index inode>"),            /* 3 */
3778         N_("<The ACL data inode>"),             /* 4 */
3779         N_("<The boot loader inode>"),          /* 5 */
3780         N_("<The undelete directory inode>"),   /* 6 */
3781         N_("<The group descriptor inode>"),     /* 7 */
3782         N_("<The journal inode>"),              /* 8 */
3783         N_("<Reserved inode 9>"),               /* 9 */
3784         N_("<Reserved inode 10>"),              /* 10 */
3785 };
3786
3787 /*
3788  * This function does "safe" printing.  It will convert non-printable
3789  * ASCII characters using '^' and M- notation.
3790  */
3791 static void safe_print(const char *cp, int len)
3792 {
3793         unsigned char   ch;
3794
3795         if (len < 0)
3796                 len = strlen(cp);
3797
3798         while (len--) {
3799                 ch = *cp++;
3800                 if (ch > 128) {
3801                         fputs("M-", stdout);
3802                         ch -= 128;
3803                 }
3804                 if ((ch < 32) || (ch == 0x7f)) {
3805                         fputc('^', stdout);
3806                         ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
3807                 }
3808                 fputc(ch, stdout);
3809         }
3810 }
3811
3812
3813 /*
3814  * This function prints a pathname, using the ext2fs_get_pathname
3815  * function
3816  */
3817 static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
3818 {
3819         errcode_t       retval;
3820         char            *path;
3821
3822         if (!dir && (ino < num_special_inodes)) {
3823                 fputs(_(special_inode_name[ino]), stdout);
3824                 return;
3825         }
3826
3827         retval = ext2fs_get_pathname(fs, dir, ino, &path);
3828         if (retval)
3829                 fputs("???", stdout);
3830         else {
3831                 safe_print(path, -1);
3832                 ext2fs_free_mem(&path);
3833         }
3834 }
3835
3836 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
3837                           struct problem_context *pctx, int first);
3838 /*
3839  * This function handles the '@' expansion.  We allow recursive
3840  * expansion; an @ expression can contain further '@' and '%'
3841  * expressions.
3842  */
3843 static void expand_at_expression(e2fsck_t ctx, char ch,
3844                                           struct problem_context *pctx,
3845                                           int *first)
3846 {
3847         const char * const *cpp;
3848         const char *str;
3849
3850         /* Search for the abbreviation */
3851         for (cpp = abbrevs; *cpp; cpp++) {
3852                 if (ch == *cpp[0])
3853                         break;
3854         }
3855         if (*cpp) {
3856                 str = _(*cpp) + 1;
3857                 if (*first && islower(*str)) {
3858                         *first = 0;
3859                         fputc(toupper(*str++), stdout);
3860                 }
3861                 print_e2fsck_message(ctx, str, pctx, *first);
3862         } else
3863                 printf("@%c", ch);
3864 }
3865
3866 /*
3867  * This function expands '%IX' expressions
3868  */
3869 static void expand_inode_expression(char ch,
3870                                              struct problem_context *ctx)
3871 {
3872         struct ext2_inode       *inode;
3873         struct ext2_inode_large *large_inode;
3874         char *                  time_str;
3875         time_t                  t;
3876         int                     do_gmt = -1;
3877
3878         if (!ctx || !ctx->inode)
3879                 goto no_inode;
3880
3881         inode = ctx->inode;
3882         large_inode = (struct ext2_inode_large *) inode;
3883
3884         switch (ch) {
3885         case 's':
3886                 if (LINUX_S_ISDIR(inode->i_mode))
3887                         printf("%u", inode->i_size);
3888                 else {
3889 #ifdef EXT2_NO_64_TYPE
3890                         if (inode->i_size_high)
3891                                 printf("0x%x%08x", inode->i_size_high,
3892                                        inode->i_size);
3893                         else
3894                                 printf("%u", inode->i_size);
3895 #else
3896                         printf("%llu", (inode->i_size |
3897                                         ((__u64) inode->i_size_high << 32)));
3898 #endif
3899                 }
3900                 break;
3901         case 'S':
3902                 printf("%u", large_inode->i_extra_isize);
3903                 break;
3904         case 'b':
3905                 printf("%u", inode->i_blocks);
3906                 break;
3907         case 'l':
3908                 printf("%d", inode->i_links_count);
3909                 break;
3910         case 'm':
3911                 printf("0%o", inode->i_mode);
3912                 break;
3913         case 'M':
3914                 /* The diet libc doesn't respect the TZ environemnt variable */
3915                 if (do_gmt == -1) {
3916                         time_str = getenv("TZ");
3917                         if (!time_str)
3918                                 time_str = "";
3919                         do_gmt = !strcmp(time_str, "GMT");
3920                 }
3921                 t = inode->i_mtime;
3922                 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
3923                 printf("%.24s", time_str);
3924                 break;
3925         case 'F':
3926                 printf("%u", inode->i_faddr);
3927                 break;
3928         case 'f':
3929                 printf("%u", inode->i_file_acl);
3930                 break;
3931         case 'd':
3932                 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
3933                               inode->i_dir_acl : 0));
3934                 break;
3935         case 'u':
3936                 printf("%d", (inode->i_uid |
3937                               (inode->osd2.linux2.l_i_uid_high << 16)));
3938                 break;
3939         case 'g':
3940                 printf("%d", (inode->i_gid |
3941                               (inode->osd2.linux2.l_i_gid_high << 16)));
3942                 break;
3943         default:
3944         no_inode:
3945                 printf("%%I%c", ch);
3946                 break;
3947         }
3948 }
3949
3950 /*
3951  * This function expands '%dX' expressions
3952  */
3953 static _INLINE_ void expand_dirent_expression(char ch,
3954                                               struct problem_context *ctx)
3955 {
3956         struct ext2_dir_entry   *dirent;
3957         int     len;
3958
3959         if (!ctx || !ctx->dirent)
3960                 goto no_dirent;
3961
3962         dirent = ctx->dirent;
3963
3964         switch (ch) {
3965         case 'i':
3966                 printf("%u", dirent->inode);
3967                 break;
3968         case 'n':
3969                 len = dirent->name_len & 0xFF;
3970                 if (len > EXT2_NAME_LEN)
3971                         len = EXT2_NAME_LEN;
3972                 if (len > dirent->rec_len)
3973                         len = dirent->rec_len;
3974                 safe_print(dirent->name, len);
3975                 break;
3976         case 'r':
3977                 printf("%u", dirent->rec_len);
3978                 break;
3979         case 'l':
3980                 printf("%u", dirent->name_len & 0xFF);
3981                 break;
3982         case 't':
3983                 printf("%u", dirent->name_len >> 8);
3984                 break;
3985         default:
3986         no_dirent:
3987                 printf("%%D%c", ch);
3988                 break;
3989         }
3990 }
3991
3992 static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
3993                                                struct problem_context *ctx)
3994 {
3995         if (!ctx)
3996                 goto no_context;
3997
3998         switch (ch) {
3999         case '%':
4000                 fputc('%', stdout);
4001                 break;
4002         case 'b':
4003                 printf("%u", ctx->blk);
4004                 break;
4005         case 'B':
4006 #ifdef EXT2_NO_64_TYPE
4007                 printf("%d", ctx->blkcount);
4008 #else
4009                 printf("%lld", ctx->blkcount);
4010 #endif
4011                 break;
4012         case 'c':
4013                 printf("%u", ctx->blk2);
4014                 break;
4015         case 'd':
4016                 printf("%u", ctx->dir);
4017                 break;
4018         case 'g':
4019                 printf("%d", ctx->group);
4020                 break;
4021         case 'i':
4022                 printf("%u", ctx->ino);
4023                 break;
4024         case 'j':
4025                 printf("%u", ctx->ino2);
4026                 break;
4027         case 'm':
4028                 printf("%s", error_message(ctx->errcode));
4029                 break;
4030         case 'N':
4031 #ifdef EXT2_NO_64_TYPE
4032                 printf("%u", ctx->num);
4033 #else
4034                 printf("%llu", ctx->num);
4035 #endif
4036                 break;
4037         case 'p':
4038                 print_pathname(fs, ctx->ino, 0);
4039                 break;
4040         case 'P':
4041                 print_pathname(fs, ctx->ino2,
4042                                ctx->dirent ? ctx->dirent->inode : 0);
4043                 break;
4044         case 'q':
4045                 print_pathname(fs, ctx->dir, 0);
4046                 break;
4047         case 'Q':
4048                 print_pathname(fs, ctx->dir, ctx->ino);
4049                 break;
4050         case 'S':
4051                 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
4052                 break;
4053         case 's':
4054                 printf("%s", ctx->str ? ctx->str : "NULL");
4055                 break;
4056         case 'X':
4057 #ifdef EXT2_NO_64_TYPE
4058                 printf("0x%x", ctx->num);
4059 #else
4060                 printf("0x%llx", ctx->num);
4061 #endif
4062                 break;
4063         default:
4064         no_context:
4065                 printf("%%%c", ch);
4066                 break;
4067         }
4068 }
4069
4070
4071 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
4072                           struct problem_context *pctx, int first)
4073 {
4074         ext2_filsys fs = ctx->fs;
4075         const char *    cp;
4076         int             i;
4077
4078         e2fsck_clear_progbar(ctx);
4079         for (cp = msg; *cp; cp++) {
4080                 if (cp[0] == '@') {
4081                         cp++;
4082                         expand_at_expression(ctx, *cp, pctx, &first);
4083                 } else if (cp[0] == '%' && cp[1] == 'I') {
4084                         cp += 2;
4085                         expand_inode_expression(*cp, pctx);
4086                 } else if (cp[0] == '%' && cp[1] == 'D') {
4087                         cp += 2;
4088                         expand_dirent_expression(*cp, pctx);
4089                 } else if ((cp[0] == '%')) {
4090                         cp++;
4091                         expand_percent_expression(fs, *cp, pctx);
4092                 } else {
4093                         for (i=0; cp[i]; i++)
4094                                 if ((cp[i] == '@') || cp[i] == '%')
4095                                         break;
4096                         printf("%.*s", i, cp);
4097                         cp += i-1;
4098                 }
4099                 first = 0;
4100         }
4101 }
4102
4103
4104 /*
4105  * region.c --- code which manages allocations within a region.
4106  */
4107
4108 struct region_el {
4109         region_addr_t   start;
4110         region_addr_t   end;
4111         struct region_el *next;
4112 };
4113
4114 struct region_struct {
4115         region_addr_t   min;
4116         region_addr_t   max;
4117         struct region_el *allocated;
4118 };
4119
4120 static region_t region_create(region_addr_t min, region_addr_t max)
4121 {
4122         region_t        region;
4123
4124         region = malloc(sizeof(struct region_struct));
4125         if (!region)
4126                 return NULL;
4127         memset(region, 0, sizeof(struct region_struct));
4128         region->min = min;
4129         region->max = max;
4130         return region;
4131 }
4132
4133 static void region_free(region_t region)
4134 {
4135         struct region_el        *r, *next;
4136
4137         for (r = region->allocated; r; r = next) {
4138                 next = r->next;
4139                 free(r);
4140         }
4141         memset(region, 0, sizeof(struct region_struct));
4142         free(region);
4143 }
4144
4145 static int region_allocate(region_t region, region_addr_t start, int n)
4146 {
4147         struct region_el        *r, *new_region, *prev, *next;
4148         region_addr_t end;
4149
4150         end = start+n;
4151         if ((start < region->min) || (end > region->max))
4152                 return -1;
4153         if (n == 0)
4154                 return 1;
4155
4156         /*
4157          * Search through the linked list.  If we find that it
4158          * conflicts witih something that's already allocated, return
4159          * 1; if we can find an existing region which we can grow, do
4160          * so.  Otherwise, stop when we find the appropriate place
4161          * insert a new region element into the linked list.
4162          */
4163         for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
4164                 if (((start >= r->start) && (start < r->end)) ||
4165                     ((end > r->start) && (end <= r->end)) ||
4166                     ((start <= r->start) && (end >= r->end)))
4167                         return 1;
4168                 if (end == r->start) {
4169                         r->start = start;
4170                         return 0;
4171                 }
4172                 if (start == r->end) {
4173                         if ((next = r->next)) {
4174                                 if (end > next->start)
4175                                         return 1;
4176                                 if (end == next->start) {
4177                                         r->end = next->end;
4178                                         r->next = next->next;
4179                                         free(next);
4180                                         return 0;
4181                                 }
4182                         }
4183                         r->end = end;
4184                         return 0;
4185                 }
4186                 if (start < r->start)
4187                         break;
4188         }
4189         /*
4190          * Insert a new region element structure into the linked list
4191          */
4192         new_region = malloc(sizeof(struct region_el));
4193         if (!new_region)
4194                 return -1;
4195         new_region->start = start;
4196         new_region->end = start + n;
4197         new_region->next = r;
4198         if (prev)
4199                 prev->next = new_region;
4200         else
4201                 region->allocated = new_region;
4202         return 0;
4203 }
4204
4205 /*
4206  * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
4207  *
4208  * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
4209  * and applies the following tests to each inode:
4210  *
4211  *      - The mode field of the inode must be legal.
4212  *      - The size and block count fields of the inode are correct.
4213  *      - A data block must not be used by another inode
4214  *
4215  * Pass 1 also gathers the collects the following information:
4216  *
4217  *      - A bitmap of which inodes are in use.          (inode_used_map)
4218  *      - A bitmap of which inodes are directories.     (inode_dir_map)
4219  *      - A bitmap of which inodes are regular files.   (inode_reg_map)
4220  *      - A bitmap of which inodes have bad fields.     (inode_bad_map)
4221  *      - A bitmap of which inodes are in bad blocks.   (inode_bb_map)
4222  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
4223  *      - A bitmap of which blocks are in use.          (block_found_map)
4224  *      - A bitmap of which blocks are in use by two inodes     (block_dup_map)
4225  *      - The data blocks of the directory inodes.      (dir_map)
4226  *
4227  * Pass 1 is designed to stash away enough information so that the
4228  * other passes should not need to read in the inode information
4229  * during the normal course of a filesystem check.  (Althogh if an
4230  * inconsistency is detected, other passes may need to read in an
4231  * inode to fix it.)
4232  *
4233  * Note that pass 1B will be invoked if there are any duplicate blocks
4234  * found.
4235  */
4236
4237
4238 static int process_block(ext2_filsys fs, blk_t  *blocknr,
4239                          e2_blkcnt_t blockcnt, blk_t ref_blk,
4240                          int ref_offset, void *priv_data);
4241 static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
4242                              e2_blkcnt_t blockcnt, blk_t ref_blk,
4243                              int ref_offset, void *priv_data);
4244 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4245                          char *block_buf);
4246 static void mark_table_blocks(e2fsck_t ctx);
4247 static void alloc_bb_map(e2fsck_t ctx);
4248 static void alloc_imagic_map(e2fsck_t ctx);
4249 static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
4250 static void handle_fs_bad_blocks(e2fsck_t ctx);
4251 static void process_inodes(e2fsck_t ctx, char *block_buf);
4252 static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b);
4253 static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan,
4254                                   dgrp_t group, void * priv_data);
4255 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
4256                                     char *block_buf, int adjust_sign);
4257 /* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
4258
4259 static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
4260                                struct ext2_inode * inode, int bufsize,
4261                                const char *proc);
4262
4263 struct process_block_struct_1 {
4264         ext2_ino_t      ino;
4265         unsigned        is_dir:1, is_reg:1, clear:1, suppress:1,
4266                                 fragmented:1, compressed:1, bbcheck:1;
4267         blk_t           num_blocks;
4268         blk_t           max_blocks;
4269         e2_blkcnt_t     last_block;
4270         int             num_illegal_blocks;
4271         blk_t           previous_block;
4272         struct ext2_inode *inode;
4273         struct problem_context *pctx;
4274         ext2fs_block_bitmap fs_meta_blocks;
4275         e2fsck_t        ctx;
4276 };
4277
4278 struct process_inode_block {
4279         ext2_ino_t ino;
4280         struct ext2_inode inode;
4281 };
4282
4283 struct scan_callback_struct {
4284         e2fsck_t        ctx;
4285         char            *block_buf;
4286 };
4287
4288 /*
4289  * For the inodes to process list.
4290  */
4291 static struct process_inode_block *inodes_to_process;
4292 static int process_inode_count;
4293
4294 static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
4295                             EXT2_MIN_BLOCK_LOG_SIZE + 1];
4296
4297 /*
4298  * Free all memory allocated by pass1 in preparation for restarting
4299  * things.
4300  */
4301 static void unwind_pass1(void)
4302 {
4303         ext2fs_free_mem(&inodes_to_process);
4304 }
4305
4306 /*
4307  * Check to make sure a device inode is real.  Returns 1 if the device
4308  * checks out, 0 if not.
4309  *
4310  * Note: this routine is now also used to check FIFO's and Sockets,
4311  * since they have the same requirement; the i_block fields should be
4312  * zero.
4313  */
4314 static int
4315 e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
4316 {
4317         int     i;
4318
4319         /*
4320          * If i_blocks is non-zero, or the index flag is set, then
4321          * this is a bogus device/fifo/socket
4322          */
4323         if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
4324             (inode->i_flags & EXT2_INDEX_FL))
4325                 return 0;
4326
4327         /*
4328          * We should be able to do the test below all the time, but
4329          * because the kernel doesn't forcibly clear the device
4330          * inode's additional i_block fields, there are some rare
4331          * occasions when a legitimate device inode will have non-zero
4332          * additional i_block fields.  So for now, we only complain
4333          * when the immutable flag is set, which should never happen
4334          * for devices.  (And that's when the problem is caused, since
4335          * you can't set or clear immutable flags for devices.)  Once
4336          * the kernel has been fixed we can change this...
4337          */
4338         if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
4339                 for (i=4; i < EXT2_N_BLOCKS; i++)
4340                         if (inode->i_block[i])
4341                                 return 0;
4342         }
4343         return 1;
4344 }
4345
4346 /*
4347  * Check to make sure a symlink inode is real.  Returns 1 if the symlink
4348  * checks out, 0 if not.
4349  */
4350 static int
4351 e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
4352 {
4353         unsigned int len;
4354         int i;
4355         blk_t   blocks;
4356
4357         if ((inode->i_size_high || inode->i_size == 0) ||
4358             (inode->i_flags & EXT2_INDEX_FL))
4359                 return 0;
4360
4361         blocks = ext2fs_inode_data_blocks(fs, inode);
4362         if (blocks) {
4363                 if ((inode->i_size >= fs->blocksize) ||
4364                     (blocks != fs->blocksize >> 9) ||
4365                     (inode->i_block[0] < fs->super->s_first_data_block) ||
4366                     (inode->i_block[0] >= fs->super->s_blocks_count))
4367                         return 0;
4368
4369                 for (i = 1; i < EXT2_N_BLOCKS; i++)
4370                         if (inode->i_block[i])
4371                                 return 0;
4372
4373                 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
4374                         return 0;
4375
4376                 len = strnlen(buf, fs->blocksize);
4377                 if (len == fs->blocksize)
4378                         return 0;
4379         } else {
4380                 if (inode->i_size >= sizeof(inode->i_block))
4381                         return 0;
4382
4383                 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
4384                 if (len == sizeof(inode->i_block))
4385                         return 0;
4386         }
4387         if (len != inode->i_size)
4388                 return 0;
4389         return 1;
4390 }
4391
4392 /*
4393  * If the immutable (or append-only) flag is set on the inode, offer
4394  * to clear it.
4395  */
4396 #define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
4397 static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
4398 {
4399         if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
4400                 return;
4401
4402         if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
4403                 return;
4404
4405         pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
4406         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
4407 }
4408
4409 /*
4410  * If device, fifo or socket, check size is zero -- if not offer to
4411  * clear it
4412  */
4413 static void check_size(e2fsck_t ctx, struct problem_context *pctx)
4414 {
4415         struct ext2_inode *inode = pctx->inode;
4416
4417         if ((inode->i_size == 0) && (inode->i_size_high == 0))
4418                 return;
4419
4420         if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
4421                 return;
4422
4423         inode->i_size = 0;
4424         inode->i_size_high = 0;
4425         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
4426 }
4427
4428 static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
4429 {
4430         struct ext2_super_block *sb = ctx->fs->super;
4431         struct ext2_inode_large *inode;
4432         struct ext2_ext_attr_entry *entry;
4433         char *start, *end;
4434         int storage_size, remain, offs;
4435         int problem = 0;
4436
4437         inode = (struct ext2_inode_large *) pctx->inode;
4438         storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
4439                 inode->i_extra_isize;
4440         start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
4441                 inode->i_extra_isize + sizeof(__u32);
4442         end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
4443         entry = (struct ext2_ext_attr_entry *) start;
4444
4445         /* scan all entry's headers first */
4446
4447         /* take finish entry 0UL into account */
4448         remain = storage_size - sizeof(__u32);
4449         offs = end - start;
4450
4451         while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
4452
4453                 /* header eats this space */
4454                 remain -= sizeof(struct ext2_ext_attr_entry);
4455
4456                 /* is attribute name valid? */
4457                 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
4458                         pctx->num = entry->e_name_len;
4459                         problem = PR_1_ATTR_NAME_LEN;
4460                         goto fix;
4461                 }
4462
4463                 /* attribute len eats this space */
4464                 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
4465
4466                 /* check value size */
4467                 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
4468                         pctx->num = entry->e_value_size;
4469                         problem = PR_1_ATTR_VALUE_SIZE;
4470                         goto fix;
4471                 }
4472
4473                 /* check value placement */
4474                 if (entry->e_value_offs +
4475                     EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
4476                         printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
4477                         pctx->num = entry->e_value_offs;
4478                         problem = PR_1_ATTR_VALUE_OFFSET;
4479                         goto fix;
4480                 }
4481
4482                 /* e_value_block must be 0 in inode's ea */
4483                 if (entry->e_value_block != 0) {
4484                         pctx->num = entry->e_value_block;
4485                         problem = PR_1_ATTR_VALUE_BLOCK;
4486                         goto fix;
4487                 }
4488
4489                 /* e_hash must be 0 in inode's ea */
4490                 if (entry->e_hash != 0) {
4491                         pctx->num = entry->e_hash;
4492                         problem = PR_1_ATTR_HASH;
4493                         goto fix;
4494                 }
4495
4496                 remain -= entry->e_value_size;
4497                 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
4498
4499                 entry = EXT2_EXT_ATTR_NEXT(entry);
4500         }
4501 fix:
4502         /*
4503          * it seems like a corruption. it's very unlikely we could repair
4504          * EA(s) in automatic fashion -bzzz
4505          */
4506 #if 0
4507         problem = PR_1_ATTR_HASH;
4508 #endif
4509         if (problem == 0 || !fix_problem(ctx, problem, pctx))
4510                 return;
4511
4512         /* simple remove all possible EA(s) */
4513         *((__u32 *)start) = 0UL;
4514         e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
4515                                 EXT2_INODE_SIZE(sb), "pass1");
4516 }
4517
4518 static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
4519 {
4520         struct ext2_super_block *sb = ctx->fs->super;
4521         struct ext2_inode_large *inode;
4522         __u32 *eamagic;
4523         int min, max;
4524
4525         inode = (struct ext2_inode_large *) pctx->inode;
4526         if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
4527                 /* this isn't large inode. so, nothing to check */
4528                 return;
4529         }
4530
4531 #if 0
4532         printf("inode #%u, i_extra_size %d\n", pctx->ino,
4533                         inode->i_extra_isize);
4534 #endif
4535         /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
4536         min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
4537         max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
4538         /*
4539          * For now we will allow i_extra_isize to be 0, but really
4540          * implementations should never allow i_extra_isize to be 0
4541          */
4542         if (inode->i_extra_isize &&
4543             (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
4544                 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
4545                         return;
4546                 inode->i_extra_isize = min;
4547                 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
4548                                         EXT2_INODE_SIZE(sb), "pass1");
4549                 return;
4550         }
4551
4552         eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
4553                         inode->i_extra_isize);
4554         if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
4555                 /* it seems inode has an extended attribute(s) in body */
4556                 check_ea_in_inode(ctx, pctx);
4557         }
4558 }
4559
4560 static void e2fsck_pass1(e2fsck_t ctx)
4561 {
4562         int     i;
4563         __u64   max_sizes;
4564         ext2_filsys fs = ctx->fs;
4565         ext2_ino_t      ino;
4566         struct ext2_inode *inode;
4567         ext2_inode_scan scan;
4568         char            *block_buf;
4569 #ifdef RESOURCE_TRACK
4570         struct resource_track   rtrack;
4571 #endif
4572         unsigned char   frag, fsize;
4573         struct          problem_context pctx;
4574         struct          scan_callback_struct scan_struct;
4575         struct ext2_super_block *sb = ctx->fs->super;
4576         int             imagic_fs;
4577         int             busted_fs_time = 0;
4578         int             inode_size;
4579
4580 #ifdef RESOURCE_TRACK
4581         init_resource_track(&rtrack);
4582 #endif
4583         clear_problem_context(&pctx);
4584
4585         if (!(ctx->options & E2F_OPT_PREEN))
4586                 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
4587
4588         if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4589             !(ctx->options & E2F_OPT_NO)) {
4590                 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
4591                         ctx->dirs_to_hash = 0;
4592         }
4593
4594 #ifdef MTRACE
4595         mtrace_print("Pass 1");
4596 #endif
4597
4598 #define EXT2_BPP(bits) (1ULL << ((bits) - 2))
4599
4600         for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
4601                 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
4602                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
4603                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
4604                 max_sizes = (max_sizes * (1UL << i)) - 1;
4605                 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
4606         }
4607 #undef EXT2_BPP
4608
4609         imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
4610
4611         /*
4612          * Allocate bitmaps structures
4613          */
4614         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
4615                                               &ctx->inode_used_map);
4616         if (pctx.errcode) {
4617                 pctx.num = 1;
4618                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4619                 ctx->flags |= E2F_FLAG_ABORT;
4620                 return;
4621         }
4622         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4623                                 _("directory inode map"), &ctx->inode_dir_map);
4624         if (pctx.errcode) {
4625                 pctx.num = 2;
4626                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4627                 ctx->flags |= E2F_FLAG_ABORT;
4628                 return;
4629         }
4630         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4631                         _("regular file inode map"), &ctx->inode_reg_map);
4632         if (pctx.errcode) {
4633                 pctx.num = 6;
4634                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4635                 ctx->flags |= E2F_FLAG_ABORT;
4636                 return;
4637         }
4638         pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
4639                                               &ctx->block_found_map);
4640         if (pctx.errcode) {
4641                 pctx.num = 1;
4642                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
4643                 ctx->flags |= E2F_FLAG_ABORT;
4644                 return;
4645         }
4646         pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
4647                                              &ctx->inode_link_info);
4648         if (pctx.errcode) {
4649                 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
4650                 ctx->flags |= E2F_FLAG_ABORT;
4651                 return;
4652         }
4653         inode_size = EXT2_INODE_SIZE(fs->super);
4654         inode = (struct ext2_inode *)
4655                 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
4656
4657         inodes_to_process = (struct process_inode_block *)
4658                 e2fsck_allocate_memory(ctx,
4659                                        (ctx->process_inode_size *
4660                                         sizeof(struct process_inode_block)),
4661                                        "array of inodes to process");
4662         process_inode_count = 0;
4663
4664         pctx.errcode = ext2fs_init_dblist(fs, 0);
4665         if (pctx.errcode) {
4666                 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
4667                 ctx->flags |= E2F_FLAG_ABORT;
4668                 return;
4669         }
4670
4671         /*
4672          * If the last orphan field is set, clear it, since the pass1
4673          * processing will automatically find and clear the orphans.
4674          * In the future, we may want to try using the last_orphan
4675          * linked list ourselves, but for now, we clear it so that the
4676          * ext3 mount code won't get confused.
4677          */
4678         if (!(ctx->options & E2F_OPT_READONLY)) {
4679                 if (fs->super->s_last_orphan) {
4680                         fs->super->s_last_orphan = 0;
4681                         ext2fs_mark_super_dirty(fs);
4682                 }
4683         }
4684
4685         mark_table_blocks(ctx);
4686         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
4687                                                     "block interate buffer");
4688         e2fsck_use_inode_shortcuts(ctx, 1);
4689         ehandler_operation(_("doing inode scan"));
4690         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4691                                               &scan);
4692         if (pctx.errcode) {
4693                 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
4694                 ctx->flags |= E2F_FLAG_ABORT;
4695                 return;
4696         }
4697         ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
4698         ctx->stashed_inode = inode;
4699         scan_struct.ctx = ctx;
4700         scan_struct.block_buf = block_buf;
4701         ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
4702         if (ctx->progress)
4703                 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
4704                         return;
4705         if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
4706             (fs->super->s_mtime < fs->super->s_inodes_count))
4707                 busted_fs_time = 1;
4708
4709         while (1) {
4710                 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
4711                                                           inode, inode_size);
4712                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4713                         return;
4714                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
4715                         if (!ctx->inode_bb_map)
4716                                 alloc_bb_map(ctx);
4717                         ext2fs_mark_inode_bitmap(ctx->inode_bb_map, ino);
4718                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4719                         continue;
4720                 }
4721                 if (pctx.errcode) {
4722                         fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
4723                         ctx->flags |= E2F_FLAG_ABORT;
4724                         return;
4725                 }
4726                 if (!ino)
4727                         break;
4728                 pctx.ino = ino;
4729                 pctx.inode = inode;
4730                 ctx->stashed_ino = ino;
4731                 if (inode->i_links_count) {
4732                         pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
4733                                            ino, inode->i_links_count);
4734                         if (pctx.errcode) {
4735                                 pctx.num = inode->i_links_count;
4736                                 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
4737                                 ctx->flags |= E2F_FLAG_ABORT;
4738                                 return;
4739                         }
4740                 }
4741                 if (ino == EXT2_BAD_INO) {
4742                         struct process_block_struct_1 pb;
4743
4744                         pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
4745                                                           &pb.fs_meta_blocks);
4746                         if (pctx.errcode) {
4747                                 pctx.num = 4;
4748                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
4749                                 ctx->flags |= E2F_FLAG_ABORT;
4750                                 return;
4751                         }
4752                         pb.ino = EXT2_BAD_INO;
4753                         pb.num_blocks = pb.last_block = 0;
4754                         pb.num_illegal_blocks = 0;
4755                         pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
4756                         pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
4757                         pb.inode = inode;
4758                         pb.pctx = &pctx;
4759                         pb.ctx = ctx;
4760                         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
4761                                      block_buf, process_bad_block, &pb);
4762                         ext2fs_free_block_bitmap(pb.fs_meta_blocks);
4763                         if (pctx.errcode) {
4764                                 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
4765                                 ctx->flags |= E2F_FLAG_ABORT;
4766                                 return;
4767                         }
4768                         if (pb.bbcheck)
4769                                 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
4770                                 ctx->flags |= E2F_FLAG_ABORT;
4771                                 return;
4772                         }
4773                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4774                         clear_problem_context(&pctx);
4775                         continue;
4776                 } else if (ino == EXT2_ROOT_INO) {
4777                         /*
4778                          * Make sure the root inode is a directory; if
4779                          * not, offer to clear it.  It will be
4780                          * regnerated in pass #3.
4781                          */
4782                         if (!LINUX_S_ISDIR(inode->i_mode)) {
4783                                 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
4784                                         inode->i_dtime = time(0);
4785                                         inode->i_links_count = 0;
4786                                         ext2fs_icount_store(ctx->inode_link_info,
4787                                                             ino, 0);
4788                                         e2fsck_write_inode(ctx, ino, inode,
4789                                                            "pass1");
4790                                 }
4791
4792                         }
4793                         /*
4794                          * If dtime is set, offer to clear it.  mke2fs
4795                          * version 0.2b created filesystems with the
4796                          * dtime field set for the root and lost+found
4797                          * directories.  We won't worry about
4798                          * /lost+found, since that can be regenerated
4799                          * easily.  But we will fix the root directory
4800                          * as a special case.
4801                          */
4802                         if (inode->i_dtime && inode->i_links_count) {
4803                                 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
4804                                         inode->i_dtime = 0;
4805                                         e2fsck_write_inode(ctx, ino, inode,
4806                                                            "pass1");
4807                                 }
4808                         }
4809                 } else if (ino == EXT2_JOURNAL_INO) {
4810                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4811                         if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
4812                                 if (!LINUX_S_ISREG(inode->i_mode) &&
4813                                     fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
4814                                                 &pctx)) {
4815                                         inode->i_mode = LINUX_S_IFREG;
4816                                         e2fsck_write_inode(ctx, ino, inode,
4817                                                            "pass1");
4818                                 }
4819                                 check_blocks(ctx, &pctx, block_buf);
4820                                 continue;
4821                         }
4822                         if ((inode->i_links_count || inode->i_blocks ||
4823                              inode->i_blocks || inode->i_block[0]) &&
4824                             fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
4825                                         &pctx)) {
4826                                 memset(inode, 0, inode_size);
4827                                 ext2fs_icount_store(ctx->inode_link_info,
4828                                                     ino, 0);
4829                                 e2fsck_write_inode_full(ctx, ino, inode,
4830                                                         inode_size, "pass1");
4831                         }
4832                 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
4833                         int     problem = 0;
4834
4835                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4836                         if (ino == EXT2_BOOT_LOADER_INO) {
4837                                 if (LINUX_S_ISDIR(inode->i_mode))
4838                                         problem = PR_1_RESERVED_BAD_MODE;
4839                         } else if (ino == EXT2_RESIZE_INO) {
4840                                 if (inode->i_mode &&
4841                                     !LINUX_S_ISREG(inode->i_mode))
4842                                         problem = PR_1_RESERVED_BAD_MODE;
4843                         } else {
4844                                 if (inode->i_mode != 0)
4845                                         problem = PR_1_RESERVED_BAD_MODE;
4846                         }
4847                         if (problem) {
4848                                 if (fix_problem(ctx, problem, &pctx)) {
4849                                         inode->i_mode = 0;
4850                                         e2fsck_write_inode(ctx, ino, inode,
4851                                                            "pass1");
4852                                 }
4853                         }
4854                         check_blocks(ctx, &pctx, block_buf);
4855                         continue;
4856                 }
4857                 /*
4858                  * Check for inodes who might have been part of the
4859                  * orphaned list linked list.  They should have gotten
4860                  * dealt with by now, unless the list had somehow been
4861                  * corrupted.
4862                  *
4863                  * FIXME: In the future, inodes which are still in use
4864                  * (and which are therefore) pending truncation should
4865                  * be handled specially.  Right now we just clear the
4866                  * dtime field, and the normal e2fsck handling of
4867                  * inodes where i_size and the inode blocks are
4868                  * inconsistent is to fix i_size, instead of releasing
4869                  * the extra blocks.  This won't catch the inodes that
4870                  * was at the end of the orphan list, but it's better
4871                  * than nothing.  The right answer is that there
4872                  * shouldn't be any bugs in the orphan list handling.  :-)
4873                  */
4874                 if (inode->i_dtime && !busted_fs_time &&
4875                     inode->i_dtime < ctx->fs->super->s_inodes_count) {
4876                         if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
4877                                 inode->i_dtime = inode->i_links_count ?
4878                                         0 : time(0);
4879                                 e2fsck_write_inode(ctx, ino, inode,
4880                                                    "pass1");
4881                         }
4882                 }
4883
4884                 /*
4885                  * This code assumes that deleted inodes have
4886                  * i_links_count set to 0.
4887                  */
4888                 if (!inode->i_links_count) {
4889                         if (!inode->i_dtime && inode->i_mode) {
4890                                 if (fix_problem(ctx,
4891                                             PR_1_ZERO_DTIME, &pctx)) {
4892                                         inode->i_dtime = time(0);
4893                                         e2fsck_write_inode(ctx, ino, inode,
4894                                                            "pass1");
4895                                 }
4896                         }
4897                         continue;
4898                 }
4899                 /*
4900                  * n.b.  0.3c ext2fs code didn't clear i_links_count for
4901                  * deleted files.  Oops.
4902                  *
4903                  * Since all new ext2 implementations get this right,
4904                  * we now assume that the case of non-zero
4905                  * i_links_count and non-zero dtime means that we
4906                  * should keep the file, not delete it.
4907                  *
4908                  */
4909                 if (inode->i_dtime) {
4910                         if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
4911                                 inode->i_dtime = 0;
4912                                 e2fsck_write_inode(ctx, ino, inode, "pass1");
4913                         }
4914                 }
4915
4916                 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4917                 switch (fs->super->s_creator_os) {
4918                     case EXT2_OS_LINUX:
4919                         frag = inode->osd2.linux2.l_i_frag;
4920                         fsize = inode->osd2.linux2.l_i_fsize;
4921                         break;
4922                     case EXT2_OS_HURD:
4923                         frag = inode->osd2.hurd2.h_i_frag;
4924                         fsize = inode->osd2.hurd2.h_i_fsize;
4925                         break;
4926                     case EXT2_OS_MASIX:
4927                         frag = inode->osd2.masix2.m_i_frag;
4928                         fsize = inode->osd2.masix2.m_i_fsize;
4929                         break;
4930                     default:
4931                         frag = fsize = 0;
4932                 }
4933
4934                 if (inode->i_faddr || frag || fsize ||
4935                     (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
4936                         mark_inode_bad(ctx, ino);
4937                 if (inode->i_flags & EXT2_IMAGIC_FL) {
4938                         if (imagic_fs) {
4939                                 if (!ctx->inode_imagic_map)
4940                                         alloc_imagic_map(ctx);
4941                                 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
4942                                                          ino);
4943                         } else {
4944                                 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
4945                                         inode->i_flags &= ~EXT2_IMAGIC_FL;
4946                                         e2fsck_write_inode(ctx, ino,
4947                                                            inode, "pass1");
4948                                 }
4949                         }
4950                 }
4951
4952                 check_inode_extra_space(ctx, &pctx);
4953
4954                 if (LINUX_S_ISDIR(inode->i_mode)) {
4955                         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
4956                         e2fsck_add_dir_info(ctx, ino, 0);
4957                         ctx->fs_directory_count++;
4958                 } else if (LINUX_S_ISREG (inode->i_mode)) {
4959                         ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
4960                         ctx->fs_regular_count++;
4961                 } else if (LINUX_S_ISCHR (inode->i_mode) &&
4962                            e2fsck_pass1_check_device_inode(fs, inode)) {
4963                         check_immutable(ctx, &pctx);
4964                         check_size(ctx, &pctx);
4965                         ctx->fs_chardev_count++;
4966                 } else if (LINUX_S_ISBLK (inode->i_mode) &&
4967                            e2fsck_pass1_check_device_inode(fs, inode)) {
4968                         check_immutable(ctx, &pctx);
4969                         check_size(ctx, &pctx);
4970                         ctx->fs_blockdev_count++;
4971                 } else if (LINUX_S_ISLNK (inode->i_mode) &&
4972                            e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
4973                         check_immutable(ctx, &pctx);
4974                         ctx->fs_symlinks_count++;
4975                         if (ext2fs_inode_data_blocks(fs, inode) == 0) {
4976                                 ctx->fs_fast_symlinks_count++;
4977                                 check_blocks(ctx, &pctx, block_buf);
4978                                 continue;
4979                         }
4980                 }
4981                 else if (LINUX_S_ISFIFO (inode->i_mode) &&
4982                          e2fsck_pass1_check_device_inode(fs, inode)) {
4983                         check_immutable(ctx, &pctx);
4984                         check_size(ctx, &pctx);
4985                         ctx->fs_fifo_count++;
4986                 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
4987                            e2fsck_pass1_check_device_inode(fs, inode)) {
4988                         check_immutable(ctx, &pctx);
4989                         check_size(ctx, &pctx);
4990                         ctx->fs_sockets_count++;
4991                 } else
4992                         mark_inode_bad(ctx, ino);
4993                 if (inode->i_block[EXT2_IND_BLOCK])
4994                         ctx->fs_ind_count++;
4995                 if (inode->i_block[EXT2_DIND_BLOCK])
4996                         ctx->fs_dind_count++;
4997                 if (inode->i_block[EXT2_TIND_BLOCK])
4998                         ctx->fs_tind_count++;
4999                 if (inode->i_block[EXT2_IND_BLOCK] ||
5000                     inode->i_block[EXT2_DIND_BLOCK] ||
5001                     inode->i_block[EXT2_TIND_BLOCK] ||
5002                     inode->i_file_acl) {
5003                         inodes_to_process[process_inode_count].ino = ino;
5004                         inodes_to_process[process_inode_count].inode = *inode;
5005                         process_inode_count++;
5006                 } else
5007                         check_blocks(ctx, &pctx, block_buf);
5008
5009                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5010                         return;
5011
5012                 if (process_inode_count >= ctx->process_inode_size) {
5013                         process_inodes(ctx, block_buf);
5014
5015                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5016                                 return;
5017                 }
5018         }
5019         process_inodes(ctx, block_buf);
5020         ext2fs_close_inode_scan(scan);
5021         ehandler_operation(0);
5022
5023         /*
5024          * If any extended attribute blocks' reference counts need to
5025          * be adjusted, either up (ctx->refcount_extra), or down
5026          * (ctx->refcount), then fix them.
5027          */
5028         if (ctx->refcount) {
5029                 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
5030                 ea_refcount_free(ctx->refcount);
5031                 ctx->refcount = 0;
5032         }
5033         if (ctx->refcount_extra) {
5034                 adjust_extattr_refcount(ctx, ctx->refcount_extra,
5035                                         block_buf, +1);
5036                 ea_refcount_free(ctx->refcount_extra);
5037                 ctx->refcount_extra = 0;
5038         }
5039
5040         if (ctx->invalid_bitmaps)
5041                 handle_fs_bad_blocks(ctx);
5042
5043         /* We don't need the block_ea_map any more */
5044         ext2fs_free_block_bitmap(ctx->block_ea_map);
5045         ctx->block_ea_map = 0;
5046
5047         if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
5048                 ext2fs_block_bitmap save_bmap;
5049
5050                 save_bmap = fs->block_map;
5051                 fs->block_map = ctx->block_found_map;
5052                 clear_problem_context(&pctx);
5053                 pctx.errcode = ext2fs_create_resize_inode(fs);
5054                 if (pctx.errcode) {
5055                         fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
5056                         /* Should never get here */
5057                         ctx->flags |= E2F_FLAG_ABORT;
5058                         return;
5059                 }
5060                 e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
5061                                   "recreate inode");
5062                 inode->i_mtime = time(0);
5063                 e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode, 
5064                                   "recreate inode");
5065                 fs->block_map = save_bmap;
5066                 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
5067         }
5068
5069         if (ctx->flags & E2F_FLAG_RESTART) {
5070                 /*
5071                  * Only the master copy of the superblock and block
5072                  * group descriptors are going to be written during a
5073                  * restart, so set the superblock to be used to be the
5074                  * master superblock.
5075                  */
5076                 ctx->use_superblock = 0;
5077                 unwind_pass1();
5078                 goto endit;
5079         }
5080
5081         if (ctx->block_dup_map) {
5082                 if (ctx->options & E2F_OPT_PREEN) {
5083                         clear_problem_context(&pctx);
5084                         fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
5085                 }
5086                 e2fsck_pass1_dupblocks(ctx, block_buf);
5087         }
5088         ext2fs_free_mem(&inodes_to_process);
5089 endit:
5090         e2fsck_use_inode_shortcuts(ctx, 0);
5091
5092         ext2fs_free_mem(&block_buf);
5093         ext2fs_free_mem(&inode);
5094
5095 #ifdef RESOURCE_TRACK
5096         if (ctx->options & E2F_OPT_TIME2) {
5097                 e2fsck_clear_progbar(ctx);
5098                 print_resource_track(_("Pass 1"), &rtrack);
5099         }
5100 #endif
5101 }
5102
5103 /*
5104  * When the inode_scan routines call this callback at the end of the
5105  * glock group, call process_inodes.
5106  */
5107 static errcode_t scan_callback(ext2_filsys fs,
5108                                ext2_inode_scan scan FSCK_ATTR((unused)),
5109                                dgrp_t group, void * priv_data)
5110 {
5111         struct scan_callback_struct *scan_struct;
5112         e2fsck_t ctx;
5113
5114         scan_struct = (struct scan_callback_struct *) priv_data;
5115         ctx = scan_struct->ctx;
5116
5117         process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
5118
5119         if (ctx->progress)
5120                 if ((ctx->progress)(ctx, 1, group+1,
5121                                     ctx->fs->group_desc_count))
5122                         return EXT2_ET_CANCEL_REQUESTED;
5123
5124         return 0;
5125 }
5126
5127 /*
5128  * Process the inodes in the "inodes to process" list.
5129  */
5130 static void process_inodes(e2fsck_t ctx, char *block_buf)
5131 {
5132         int                     i;
5133         struct ext2_inode       *old_stashed_inode;
5134         ext2_ino_t              old_stashed_ino;
5135         const char              *old_operation;
5136         char                    buf[80];
5137         struct problem_context  pctx;
5138
5139 #if 0
5140         printf("begin process_inodes: ");
5141 #endif
5142         if (process_inode_count == 0)
5143                 return;
5144         old_operation = ehandler_operation(0);
5145         old_stashed_inode = ctx->stashed_inode;
5146         old_stashed_ino = ctx->stashed_ino;
5147         qsort(inodes_to_process, process_inode_count,
5148                       sizeof(struct process_inode_block), process_inode_cmp);
5149         clear_problem_context(&pctx);
5150         for (i=0; i < process_inode_count; i++) {
5151                 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
5152                 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
5153
5154 #if 0
5155                 printf("%u ", pctx.ino);
5156 #endif
5157                 sprintf(buf, _("reading indirect blocks of inode %u"),
5158                         pctx.ino);
5159                 ehandler_operation(buf);
5160                 check_blocks(ctx, &pctx, block_buf);
5161                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5162                         break;
5163         }
5164         ctx->stashed_inode = old_stashed_inode;
5165         ctx->stashed_ino = old_stashed_ino;
5166         process_inode_count = 0;
5167 #if 0
5168         printf("end process inodes\n");
5169 #endif
5170         ehandler_operation(old_operation);
5171 }
5172
5173 static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b)
5174 {
5175         const struct process_inode_block *ib_a =
5176                 (const struct process_inode_block *) a;
5177         const struct process_inode_block *ib_b =
5178                 (const struct process_inode_block *) b;
5179         int     ret;
5180
5181         ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
5182                ib_b->inode.i_block[EXT2_IND_BLOCK]);
5183         if (ret == 0)
5184                 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
5185         return ret;
5186 }
5187
5188 /*
5189  * Mark an inode as being bad in some what
5190  */
5191 static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
5192 {
5193         struct          problem_context pctx;
5194
5195         if (!ctx->inode_bad_map) {
5196                 clear_problem_context(&pctx);
5197
5198                 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
5199                             _("bad inode map"), &ctx->inode_bad_map);
5200                 if (pctx.errcode) {
5201                         pctx.num = 3;
5202                         fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
5203                         /* Should never get here */
5204                         ctx->flags |= E2F_FLAG_ABORT;
5205                         return;
5206                 }
5207         }
5208         ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
5209 }
5210
5211
5212 /*
5213  * This procedure will allocate the inode "bb" (badblock) map table
5214  */
5215 static void alloc_bb_map(e2fsck_t ctx)
5216 {
5217         struct          problem_context pctx;
5218
5219         clear_problem_context(&pctx);
5220         pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
5221                                               _("inode in bad block map"),
5222                                               &ctx->inode_bb_map);
5223         if (pctx.errcode) {
5224                 pctx.num = 4;
5225                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
5226                 /* Should never get here */
5227                 ctx->flags |= E2F_FLAG_ABORT;
5228                 return;
5229         }
5230 }
5231
5232 /*
5233  * This procedure will allocate the inode imagic table
5234  */
5235 static void alloc_imagic_map(e2fsck_t ctx)
5236 {
5237         struct          problem_context pctx;
5238
5239         clear_problem_context(&pctx);
5240         pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
5241                                               _("imagic inode map"),
5242                                               &ctx->inode_imagic_map);
5243         if (pctx.errcode) {
5244                 pctx.num = 5;
5245                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
5246                 /* Should never get here */
5247                 ctx->flags |= E2F_FLAG_ABORT;
5248                 return;
5249         }
5250 }
5251
5252 /*
5253  * Marks a block as in use, setting the dup_map if it's been set
5254  * already.  Called by process_block and process_bad_block.
5255  *
5256  * WARNING: Assumes checks have already been done to make sure block
5257  * is valid.  This is true in both process_block and process_bad_block.
5258  */
5259 static _INLINE_ void mark_block_used(e2fsck_t ctx, blk_t block)
5260 {
5261         struct          problem_context pctx;
5262
5263         clear_problem_context(&pctx);
5264
5265         if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
5266                 if (!ctx->block_dup_map) {
5267                         pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
5268                               _("multiply claimed block map"),
5269                               &ctx->block_dup_map);
5270                         if (pctx.errcode) {
5271                                 pctx.num = 3;
5272                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
5273                                             &pctx);
5274                                 /* Should never get here */
5275                                 ctx->flags |= E2F_FLAG_ABORT;
5276                                 return;
5277                         }
5278                 }
5279                 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
5280         } else {
5281                 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
5282         }
5283 }
5284
5285 /*
5286  * Adjust the extended attribute block's reference counts at the end
5287  * of pass 1, either by subtracting out references for EA blocks that
5288  * are still referenced in ctx->refcount, or by adding references for
5289  * EA blocks that had extra references as accounted for in
5290  * ctx->refcount_extra.
5291  */
5292 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
5293                                     char *block_buf, int adjust_sign)
5294 {
5295         struct ext2_ext_attr_header     *header;
5296         struct problem_context          pctx;
5297         ext2_filsys                     fs = ctx->fs;
5298         blk_t                           blk;
5299         __u32                           should_be;
5300         int                             count;
5301
5302         clear_problem_context(&pctx);
5303
5304         ea_refcount_intr_begin(refcount);
5305         while (1) {
5306                 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
5307                         break;
5308                 pctx.blk = blk;
5309                 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
5310                 if (pctx.errcode) {
5311                         fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
5312                         return;
5313                 }
5314                 header = (struct ext2_ext_attr_header *) block_buf;
5315                 pctx.blkcount = header->h_refcount;
5316                 should_be = header->h_refcount + adjust_sign * count;
5317                 pctx.num = should_be;
5318                 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
5319                         header->h_refcount = should_be;
5320                         pctx.errcode = ext2fs_write_ext_attr(fs, blk,
5321                                                              block_buf);
5322                         if (pctx.errcode) {
5323                                 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
5324                                 continue;
5325                         }
5326                 }
5327         }
5328 }
5329
5330 /*
5331  * Handle processing the extended attribute blocks
5332  */
5333 static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
5334                            char *block_buf)
5335 {
5336         ext2_filsys fs = ctx->fs;
5337         ext2_ino_t      ino = pctx->ino;
5338         struct ext2_inode *inode = pctx->inode;
5339         blk_t           blk;
5340         char *          end;
5341         struct ext2_ext_attr_header *header;
5342         struct ext2_ext_attr_entry *entry;
5343         int             count;
5344         region_t        region;
5345
5346         blk = inode->i_file_acl;
5347         if (blk == 0)
5348                 return 0;
5349
5350         /*
5351          * If the Extended attribute flag isn't set, then a non-zero
5352          * file acl means that the inode is corrupted.
5353          *
5354          * Or if the extended attribute block is an invalid block,
5355          * then the inode is also corrupted.
5356          */
5357         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
5358             (blk < fs->super->s_first_data_block) ||
5359             (blk >= fs->super->s_blocks_count)) {
5360                 mark_inode_bad(ctx, ino);
5361                 return 0;
5362         }
5363
5364         /* If ea bitmap hasn't been allocated, create it */
5365         if (!ctx->block_ea_map) {
5366                 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
5367                                                       _("ext attr block map"),
5368                                                       &ctx->block_ea_map);
5369                 if (pctx->errcode) {
5370                         pctx->num = 2;
5371                         fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
5372                         ctx->flags |= E2F_FLAG_ABORT;
5373                         return 0;
5374                 }
5375         }
5376
5377         /* Create the EA refcount structure if necessary */
5378         if (!ctx->refcount) {
5379                 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
5380                 if (pctx->errcode) {
5381                         pctx->num = 1;
5382                         fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
5383                         ctx->flags |= E2F_FLAG_ABORT;
5384                         return 0;
5385                 }
5386         }
5387
5388 #if 0
5389         /* Debugging text */
5390         printf("Inode %u has EA block %u\n", ino, blk);
5391 #endif
5392
5393         /* Have we seen this EA block before? */
5394         if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
5395                 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
5396                         return 1;
5397                 /* Ooops, this EA was referenced more than it stated */
5398                 if (!ctx->refcount_extra) {
5399                         pctx->errcode = ea_refcount_create(0,
5400                                            &ctx->refcount_extra);
5401                         if (pctx->errcode) {
5402                                 pctx->num = 2;
5403                                 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
5404                                 ctx->flags |= E2F_FLAG_ABORT;
5405                                 return 0;
5406                         }
5407                 }
5408                 ea_refcount_increment(ctx->refcount_extra, blk, 0);
5409                 return 1;
5410         }
5411
5412         /*
5413          * OK, we haven't seen this EA block yet.  So we need to
5414          * validate it
5415          */
5416         pctx->blk = blk;
5417         pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
5418         if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
5419                 goto clear_extattr;
5420         header = (struct ext2_ext_attr_header *) block_buf;
5421         pctx->blk = inode->i_file_acl;
5422         if (((ctx->ext_attr_ver == 1) &&
5423              (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
5424             ((ctx->ext_attr_ver == 2) &&
5425              (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
5426                 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
5427                         goto clear_extattr;
5428         }
5429
5430         if (header->h_blocks != 1) {
5431                 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
5432                         goto clear_extattr;
5433         }
5434
5435         region = region_create(0, fs->blocksize);
5436         if (!region) {
5437                 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
5438                 ctx->flags |= E2F_FLAG_ABORT;
5439                 return 0;
5440         }
5441         if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
5442                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5443                         goto clear_extattr;
5444         }
5445
5446         entry = (struct ext2_ext_attr_entry *)(header+1);
5447         end = block_buf + fs->blocksize;
5448         while ((char *)entry < end && *(__u32 *)entry) {
5449                 if (region_allocate(region, (char *)entry - (char *)header,
5450                                    EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
5451                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5452                                 goto clear_extattr;
5453                 }
5454                 if ((ctx->ext_attr_ver == 1 &&
5455                      (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
5456                     (ctx->ext_attr_ver == 2 &&
5457                      entry->e_name_index == 0)) {
5458                         if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
5459                                 goto clear_extattr;
5460                 }
5461                 if (entry->e_value_block != 0) {
5462                         if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
5463                                 goto clear_extattr;
5464                 }
5465                 if (entry->e_value_size &&
5466                     region_allocate(region, entry->e_value_offs,
5467                                     EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
5468                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5469                                 goto clear_extattr;
5470                 }
5471                 entry = EXT2_EXT_ATTR_NEXT(entry);
5472         }
5473         if (region_allocate(region, (char *)entry - (char *)header, 4)) {
5474                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5475                         goto clear_extattr;
5476         }
5477         region_free(region);
5478
5479         count = header->h_refcount - 1;
5480         if (count)
5481                 ea_refcount_store(ctx->refcount, blk, count);
5482         mark_block_used(ctx, blk);
5483         ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
5484
5485         return 1;
5486
5487 clear_extattr:
5488         inode->i_file_acl = 0;
5489         e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
5490         return 0;
5491 }
5492
5493 /* Returns 1 if bad htree, 0 if OK */
5494 static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
5495                         ext2_ino_t ino FSCK_ATTR((unused)),
5496                         struct ext2_inode *inode,
5497                         char *block_buf)
5498 {
5499         struct ext2_dx_root_info        *root;
5500         ext2_filsys                     fs = ctx->fs;
5501         errcode_t                       retval;
5502         blk_t                           blk;
5503
5504         if ((!LINUX_S_ISDIR(inode->i_mode) &&
5505              fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
5506             (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
5507              fix_problem(ctx, PR_1_HTREE_SET, pctx)))
5508                 return 1;
5509
5510         blk = inode->i_block[0];
5511         if (((blk == 0) ||
5512              (blk < fs->super->s_first_data_block) ||
5513              (blk >= fs->super->s_blocks_count)) &&
5514             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5515                 return 1;
5516
5517         retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
5518         if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5519                 return 1;
5520
5521         /* XXX should check that beginning matches a directory */
5522         root = (struct ext2_dx_root_info *) (block_buf + 24);
5523
5524         if ((root->reserved_zero || root->info_length < 8) &&
5525             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5526                 return 1;
5527
5528         pctx->num = root->hash_version;
5529         if ((root->hash_version != EXT2_HASH_LEGACY) &&
5530             (root->hash_version != EXT2_HASH_HALF_MD4) &&
5531             (root->hash_version != EXT2_HASH_TEA) &&
5532             fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
5533                 return 1;
5534
5535         if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
5536             fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
5537                 return 1;
5538
5539         pctx->num = root->indirect_levels;
5540         if ((root->indirect_levels > 1) &&
5541             fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
5542                 return 1;
5543
5544         return 0;
5545 }
5546
5547 /*
5548  * This subroutine is called on each inode to account for all of the
5549  * blocks used by that inode.
5550  */
5551 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
5552                          char *block_buf)
5553 {
5554         ext2_filsys fs = ctx->fs;
5555         struct process_block_struct_1 pb;
5556         ext2_ino_t      ino = pctx->ino;
5557         struct ext2_inode *inode = pctx->inode;
5558         int             bad_size = 0;
5559         int             dirty_inode = 0;
5560         __u64           size;
5561
5562         pb.ino = ino;
5563         pb.num_blocks = 0;
5564         pb.last_block = -1;
5565         pb.num_illegal_blocks = 0;
5566         pb.suppress = 0; pb.clear = 0;
5567         pb.fragmented = 0;
5568         pb.compressed = 0;
5569         pb.previous_block = 0;
5570         pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
5571         pb.is_reg = LINUX_S_ISREG(inode->i_mode);
5572         pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
5573         pb.inode = inode;
5574         pb.pctx = pctx;
5575         pb.ctx = ctx;
5576         pctx->ino = ino;
5577         pctx->errcode = 0;
5578
5579         if (inode->i_flags & EXT2_COMPRBLK_FL) {
5580                 if (fs->super->s_feature_incompat &
5581                     EXT2_FEATURE_INCOMPAT_COMPRESSION)
5582                         pb.compressed = 1;
5583                 else {
5584                         if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
5585                                 inode->i_flags &= ~EXT2_COMPRBLK_FL;
5586                                 dirty_inode++;
5587                         }
5588                 }
5589         }
5590
5591         if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
5592                 pb.num_blocks++;
5593
5594         if (ext2fs_inode_has_valid_blocks(inode))
5595                 pctx->errcode = ext2fs_block_iterate2(fs, ino,
5596                                        pb.is_dir ? BLOCK_FLAG_HOLE : 0,
5597                                        block_buf, process_block, &pb);
5598         end_problem_latch(ctx, PR_LATCH_BLOCK);
5599         end_problem_latch(ctx, PR_LATCH_TOOBIG);
5600         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5601                 goto out;
5602         if (pctx->errcode)
5603                 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
5604
5605         if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
5606                 ctx->fs_fragmented++;
5607
5608         if (pb.clear) {
5609                 inode->i_links_count = 0;
5610                 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
5611                 inode->i_dtime = time(0);
5612                 dirty_inode++;
5613                 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5614                 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
5615                 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5616                 /*
5617                  * The inode was probably partially accounted for
5618                  * before processing was aborted, so we need to
5619                  * restart the pass 1 scan.
5620                  */
5621                 ctx->flags |= E2F_FLAG_RESTART;
5622                 goto out;
5623         }
5624
5625         if (inode->i_flags & EXT2_INDEX_FL) {
5626                 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
5627                         inode->i_flags &= ~EXT2_INDEX_FL;
5628                         dirty_inode++;
5629                 } else {
5630 #ifdef ENABLE_HTREE
5631                         e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
5632 #endif
5633                 }
5634         }
5635         if (ctx->dirs_to_hash && pb.is_dir &&
5636             !(inode->i_flags & EXT2_INDEX_FL) &&
5637             ((inode->i_size / fs->blocksize) >= 3))
5638                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
5639
5640         if (!pb.num_blocks && pb.is_dir) {
5641                 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
5642                         inode->i_links_count = 0;
5643                         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
5644                         inode->i_dtime = time(0);
5645                         dirty_inode++;
5646                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5647                         ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
5648                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5649                         ctx->fs_directory_count--;
5650                         goto out;
5651                 }
5652         }
5653
5654         pb.num_blocks *= (fs->blocksize / 512);
5655 #if 0
5656         printf("inode %u, i_size = %lu, last_block = %lld, i_blocks=%lu, num_blocks = %lu\n",
5657                ino, inode->i_size, pb.last_block, inode->i_blocks,
5658                pb.num_blocks);
5659 #endif
5660         if (pb.is_dir) {
5661                 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
5662                 if (nblock > (pb.last_block + 1))
5663                         bad_size = 1;
5664                 else if (nblock < (pb.last_block + 1)) {
5665                         if (((pb.last_block + 1) - nblock) >
5666                             fs->super->s_prealloc_dir_blocks)
5667                                 bad_size = 2;
5668                 }
5669         } else {
5670                 size = EXT2_I_SIZE(inode);
5671                 if ((pb.last_block >= 0) &&
5672                     (size < (__u64) pb.last_block * fs->blocksize))
5673                         bad_size = 3;
5674                 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
5675                         bad_size = 4;
5676         }
5677         /* i_size for symlinks is checked elsewhere */
5678         if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
5679                 pctx->num = (pb.last_block+1) * fs->blocksize;
5680                 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
5681                         inode->i_size = pctx->num;
5682                         if (!LINUX_S_ISDIR(inode->i_mode))
5683                                 inode->i_size_high = pctx->num >> 32;
5684                         dirty_inode++;
5685                 }
5686                 pctx->num = 0;
5687         }
5688         if (LINUX_S_ISREG(inode->i_mode) &&
5689             (inode->i_size_high || inode->i_size & 0x80000000UL))
5690                 ctx->large_files++;
5691         if (pb.num_blocks != inode->i_blocks) {
5692                 pctx->num = pb.num_blocks;
5693                 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
5694                         inode->i_blocks = pb.num_blocks;
5695                         dirty_inode++;
5696                 }
5697                 pctx->num = 0;
5698         }
5699 out:
5700         if (dirty_inode)
5701                 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
5702 }
5703
5704 #if 0
5705 /*
5706  * Helper function called by process block when an illegal block is
5707  * found.  It returns a description about why the block is illegal
5708  */
5709 static char *describe_illegal_block(ext2_filsys fs, blk_t block)
5710 {
5711         blk_t   super;
5712         int     i;
5713         static char     problem[80];
5714
5715         super = fs->super->s_first_data_block;
5716         strcpy(problem, "PROGRAMMING ERROR: Unknown reason for illegal block");
5717         if (block < super) {
5718                 sprintf(problem, "< FIRSTBLOCK (%u)", super);
5719                 return(problem);
5720         } else if (block >= fs->super->s_blocks_count) {
5721                 sprintf(problem, "> BLOCKS (%u)", fs->super->s_blocks_count);
5722                 return(problem);
5723         }
5724         for (i = 0; i < fs->group_desc_count; i++) {
5725                 if (block == super) {
5726                         sprintf(problem, "is the superblock in group %d", i);
5727                         break;
5728                 }
5729                 if (block > super &&
5730                     block <= (super + fs->desc_blocks)) {
5731                         sprintf(problem, "is in the group descriptors "
5732                                 "of group %d", i);
5733                         break;
5734                 }
5735                 if (block == fs->group_desc[i].bg_block_bitmap) {
5736                         sprintf(problem, "is the block bitmap of group %d", i);
5737                         break;
5738                 }
5739                 if (block == fs->group_desc[i].bg_inode_bitmap) {
5740                         sprintf(problem, "is the inode bitmap of group %d", i);
5741                         break;
5742                 }
5743                 if (block >= fs->group_desc[i].bg_inode_table &&
5744                     (block < fs->group_desc[i].bg_inode_table
5745                      + fs->inode_blocks_per_group)) {
5746                         sprintf(problem, "is in the inode table of group %d",
5747                                 i);
5748                         break;
5749                 }
5750                 super += fs->super->s_blocks_per_group;
5751         }
5752         return(problem);
5753 }
5754 #endif
5755
5756 /*
5757  * This is a helper function for check_blocks().
5758  */
5759 static int process_block(ext2_filsys fs,
5760                   blk_t *block_nr,
5761                   e2_blkcnt_t blockcnt,
5762                   blk_t ref_block FSCK_ATTR((unused)),
5763                   int ref_offset FSCK_ATTR((unused)),
5764                   void *priv_data)
5765 {
5766         struct process_block_struct_1 *p;
5767         struct problem_context *pctx;
5768         blk_t   blk = *block_nr;
5769         int     ret_code = 0;
5770         int     problem = 0;
5771         e2fsck_t        ctx;
5772
5773         p = (struct process_block_struct_1 *) priv_data;
5774         pctx = p->pctx;
5775         ctx = p->ctx;
5776
5777         if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
5778                 /* todo: Check that the comprblk_fl is high, that the
5779                    blkaddr pattern looks right (all non-holes up to
5780                    first EXT2FS_COMPRESSED_BLKADDR, then all
5781                    EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
5782                    that the feature_incompat bit is high, and that the
5783                    inode is a regular file.  If we're doing a "full
5784                    check" (a concept introduced to e2fsck by e2compr,
5785                    meaning that we look at data blocks as well as
5786                    metadata) then call some library routine that
5787                    checks the compressed data.  I'll have to think
5788                    about this, because one particularly important
5789                    problem to be able to fix is to recalculate the
5790                    cluster size if necessary.  I think that perhaps
5791                    we'd better do most/all e2compr-specific checks
5792                    separately, after the non-e2compr checks.  If not
5793                    doing a full check, it may be useful to test that
5794                    the personality is linux; e.g. if it isn't then
5795                    perhaps this really is just an illegal block. */
5796                 return 0;
5797         }
5798
5799         if (blk == 0) {
5800                 if (p->is_dir == 0) {
5801                         /*
5802                          * Should never happen, since only directories
5803                          * get called with BLOCK_FLAG_HOLE
5804                          */
5805 #if DEBUG_E2FSCK
5806                         printf("process_block() called with blk == 0, "
5807                                "blockcnt=%d, inode %lu???\n",
5808                                blockcnt, p->ino);
5809 #endif
5810                         return 0;
5811                 }
5812                 if (blockcnt < 0)
5813                         return 0;
5814                 if (blockcnt * fs->blocksize < p->inode->i_size) {
5815 #if 0
5816                         printf("Missing block (#%d) in directory inode %lu!\n",
5817                                blockcnt, p->ino);
5818 #endif
5819                         goto mark_dir;
5820                 }
5821                 return 0;
5822         }
5823
5824 #if 0
5825         printf("Process_block, inode %lu, block %u, #%d\n", p->ino, blk,
5826                blockcnt);
5827 #endif
5828
5829         /*
5830          * Simplistic fragmentation check.  We merely require that the
5831          * file be contiguous.  (Which can never be true for really
5832          * big files that are greater than a block group.)
5833          */
5834         if (!HOLE_BLKADDR(p->previous_block)) {
5835                 if (p->previous_block+1 != blk)
5836                         p->fragmented = 1;
5837         }
5838         p->previous_block = blk;
5839
5840         if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
5841                 problem = PR_1_TOOBIG_DIR;
5842         if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
5843                 problem = PR_1_TOOBIG_REG;
5844         if (!p->is_dir && !p->is_reg && blockcnt > 0)
5845                 problem = PR_1_TOOBIG_SYMLINK;
5846
5847         if (blk < fs->super->s_first_data_block ||
5848             blk >= fs->super->s_blocks_count)
5849                 problem = PR_1_ILLEGAL_BLOCK_NUM;
5850
5851         if (problem) {
5852                 p->num_illegal_blocks++;
5853                 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
5854                         if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
5855                                 p->clear = 1;
5856                                 return BLOCK_ABORT;
5857                         }
5858                         if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
5859                                 p->suppress = 1;
5860                                 set_latch_flags(PR_LATCH_BLOCK,
5861                                                 PRL_SUPPRESS, 0);
5862                         }
5863                 }
5864                 pctx->blk = blk;
5865                 pctx->blkcount = blockcnt;
5866                 if (fix_problem(ctx, problem, pctx)) {
5867                         blk = *block_nr = 0;
5868                         ret_code = BLOCK_CHANGED;
5869                         goto mark_dir;
5870                 } else
5871                         return 0;
5872         }
5873
5874         if (p->ino == EXT2_RESIZE_INO) {
5875                 /*
5876                  * The resize inode has already be sanity checked
5877                  * during pass #0 (the superblock checks).  All we
5878                  * have to do is mark the double indirect block as
5879                  * being in use; all of the other blocks are handled
5880                  * by mark_table_blocks()).
5881                  */
5882                 if (blockcnt == BLOCK_COUNT_DIND)
5883                         mark_block_used(ctx, blk);
5884         } else
5885                 mark_block_used(ctx, blk);
5886         p->num_blocks++;
5887         if (blockcnt >= 0)
5888                 p->last_block = blockcnt;
5889 mark_dir:
5890         if (p->is_dir && (blockcnt >= 0)) {
5891                 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
5892                                                     blk, blockcnt);
5893                 if (pctx->errcode) {
5894                         pctx->blk = blk;
5895                         pctx->num = blockcnt;
5896                         fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
5897                         /* Should never get here */
5898                         ctx->flags |= E2F_FLAG_ABORT;
5899                         return BLOCK_ABORT;
5900                 }
5901         }
5902         return ret_code;
5903 }
5904
5905 static int process_bad_block(ext2_filsys fs,
5906                       blk_t *block_nr,
5907                       e2_blkcnt_t blockcnt,
5908                       blk_t ref_block FSCK_ATTR((unused)),
5909                       int ref_offset FSCK_ATTR((unused)),
5910                       void *priv_data)
5911 {
5912         struct process_block_struct_1 *p;
5913         blk_t           blk = *block_nr;
5914         blk_t           first_block;
5915         dgrp_t          i;
5916         struct problem_context *pctx;
5917         e2fsck_t        ctx;
5918
5919         /*
5920          * Note: This function processes blocks for the bad blocks
5921          * inode, which is never compressed.  So we don't use HOLE_BLKADDR().
5922          */
5923
5924         if (!blk)
5925                 return 0;
5926
5927         p = (struct process_block_struct_1 *) priv_data;
5928         ctx = p->ctx;
5929         pctx = p->pctx;
5930
5931         pctx->ino = EXT2_BAD_INO;
5932         pctx->blk = blk;
5933         pctx->blkcount = blockcnt;
5934
5935         if ((blk < fs->super->s_first_data_block) ||
5936             (blk >= fs->super->s_blocks_count)) {
5937                 if (fix_problem(ctx, PR_1_BB_ILLEGAL_BLOCK_NUM, pctx)) {
5938                         *block_nr = 0;
5939                         return BLOCK_CHANGED;
5940                 } else
5941                         return 0;
5942         }
5943
5944         if (blockcnt < 0) {
5945                 if (ext2fs_test_block_bitmap(p->fs_meta_blocks, blk)) {
5946                         p->bbcheck = 1;
5947                         if (fix_problem(ctx, PR_1_BB_FS_BLOCK, pctx)) {
5948                                 *block_nr = 0;
5949                                 return BLOCK_CHANGED;
5950                         }
5951                 } else if (ext2fs_test_block_bitmap(ctx->block_found_map,
5952                                                     blk)) {
5953                         p->bbcheck = 1;
5954                         if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK,
5955                                         pctx)) {
5956                                 *block_nr = 0;
5957                                 return BLOCK_CHANGED;
5958                         }
5959                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5960                                 return BLOCK_ABORT;
5961                 } else
5962                         mark_block_used(ctx, blk);
5963                 return 0;
5964         }
5965 #if 0
5966         printf ("DEBUG: Marking %u as bad.\n", blk);
5967 #endif
5968         ctx->fs_badblocks_count++;
5969         /*
5970          * If the block is not used, then mark it as used and return.
5971          * If it is already marked as found, this must mean that
5972          * there's an overlap between the filesystem table blocks
5973          * (bitmaps and inode table) and the bad block list.
5974          */
5975         if (!ext2fs_test_block_bitmap(ctx->block_found_map, blk)) {
5976                 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
5977                 return 0;
5978         }
5979         /*
5980          * Try to find the where the filesystem block was used...
5981          */
5982         first_block = fs->super->s_first_data_block;
5983
5984         for (i = 0; i < fs->group_desc_count; i++ ) {
5985                 pctx->group = i;
5986                 pctx->blk = blk;
5987                 if (!ext2fs_bg_has_super(fs, i))
5988                         goto skip_super;
5989                 if (blk == first_block) {
5990                         if (i == 0) {
5991                                 if (fix_problem(ctx,
5992                                                 PR_1_BAD_PRIMARY_SUPERBLOCK,
5993                                                 pctx)) {
5994                                         *block_nr = 0;
5995                                         return BLOCK_CHANGED;
5996                                 }
5997                                 return 0;
5998                         }
5999                         fix_problem(ctx, PR_1_BAD_SUPERBLOCK, pctx);
6000                         return 0;
6001                 }
6002                 if ((blk > first_block) &&
6003                     (blk <= first_block + fs->desc_blocks)) {
6004                         if (i == 0) {
6005                                 pctx->blk = *block_nr;
6006                                 if (fix_problem(ctx,
6007                         PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR, pctx)) {
6008                                         *block_nr = 0;
6009                                         return BLOCK_CHANGED;
6010                                 }
6011                                 return 0;
6012                         }
6013                         fix_problem(ctx, PR_1_BAD_GROUP_DESCRIPTORS, pctx);
6014                         return 0;
6015                 }
6016         skip_super:
6017                 if (blk == fs->group_desc[i].bg_block_bitmap) {
6018                         if (fix_problem(ctx, PR_1_BB_BAD_BLOCK, pctx)) {
6019                                 ctx->invalid_block_bitmap_flag[i]++;
6020                                 ctx->invalid_bitmaps++;
6021                         }
6022                         return 0;
6023                 }
6024                 if (blk == fs->group_desc[i].bg_inode_bitmap) {
6025                         if (fix_problem(ctx, PR_1_IB_BAD_BLOCK, pctx)) {
6026                                 ctx->invalid_inode_bitmap_flag[i]++;
6027                                 ctx->invalid_bitmaps++;
6028                         }
6029                         return 0;
6030                 }
6031                 if ((blk >= fs->group_desc[i].bg_inode_table) &&
6032                     (blk < (fs->group_desc[i].bg_inode_table +
6033                             fs->inode_blocks_per_group))) {
6034                         /*
6035                          * If there are bad blocks in the inode table,
6036                          * the inode scan code will try to do
6037                          * something reasonable automatically.
6038                          */
6039                         return 0;
6040                 }
6041                 first_block += fs->super->s_blocks_per_group;
6042         }
6043         /*
6044          * If we've gotten to this point, then the only
6045          * possibility is that the bad block inode meta data
6046          * is using a bad block.
6047          */
6048         if ((blk == p->inode->i_block[EXT2_IND_BLOCK]) ||
6049             (blk == p->inode->i_block[EXT2_DIND_BLOCK]) ||
6050             (blk == p->inode->i_block[EXT2_TIND_BLOCK])) {
6051                 p->bbcheck = 1;
6052                 if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK, pctx)) {
6053                         *block_nr = 0;
6054                         return BLOCK_CHANGED;
6055                 }
6056                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6057                         return BLOCK_ABORT;
6058                 return 0;
6059         }
6060
6061         pctx->group = -1;
6062
6063         /* Warn user that the block wasn't claimed */
6064         fix_problem(ctx, PR_1_PROGERR_CLAIMED_BLOCK, pctx);
6065
6066         return 0;
6067 }
6068
6069 static void new_table_block(e2fsck_t ctx, blk_t first_block, int group,
6070                             const char *name, int num, blk_t *new_block)
6071 {
6072         ext2_filsys fs = ctx->fs;
6073         blk_t           old_block = *new_block;
6074         int             i;
6075         char            *buf;
6076         struct problem_context  pctx;
6077
6078         clear_problem_context(&pctx);
6079
6080         pctx.group = group;
6081         pctx.blk = old_block;
6082         pctx.str = name;
6083
6084         pctx.errcode = ext2fs_get_free_blocks(fs, first_block,
6085                         first_block + fs->super->s_blocks_per_group,
6086                                         num, ctx->block_found_map, new_block);
6087         if (pctx.errcode) {
6088                 pctx.num = num;
6089                 fix_problem(ctx, PR_1_RELOC_BLOCK_ALLOCATE, &pctx);
6090                 ext2fs_unmark_valid(fs);
6091                 return;
6092         }
6093         pctx.errcode = ext2fs_get_mem(fs->blocksize, &buf);
6094         if (pctx.errcode) {
6095                 fix_problem(ctx, PR_1_RELOC_MEMORY_ALLOCATE, &pctx);
6096                 ext2fs_unmark_valid(fs);
6097                 return;
6098         }
6099         ext2fs_mark_super_dirty(fs);
6100         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
6101         pctx.blk2 = *new_block;
6102         fix_problem(ctx, (old_block ? PR_1_RELOC_FROM_TO :
6103                           PR_1_RELOC_TO), &pctx);
6104         pctx.blk2 = 0;
6105         for (i = 0; i < num; i++) {
6106                 pctx.blk = i;
6107                 ext2fs_mark_block_bitmap(ctx->block_found_map, (*new_block)+i);
6108                 if (old_block) {
6109                         pctx.errcode = io_channel_read_blk(fs->io,
6110                                    old_block + i, 1, buf);
6111                         if (pctx.errcode)
6112                                 fix_problem(ctx, PR_1_RELOC_READ_ERR, &pctx);
6113                 } else
6114                         memset(buf, 0, fs->blocksize);
6115
6116                 pctx.blk = (*new_block) + i;
6117                 pctx.errcode = io_channel_write_blk(fs->io, pctx.blk,
6118                                               1, buf);
6119                 if (pctx.errcode)
6120                         fix_problem(ctx, PR_1_RELOC_WRITE_ERR, &pctx);
6121         }
6122         ext2fs_free_mem(&buf);
6123 }
6124
6125 /*
6126  * This routine gets called at the end of pass 1 if bad blocks are
6127  * detected in the superblock, group descriptors, inode_bitmaps, or
6128  * block bitmaps.  At this point, all of the blocks have been mapped
6129  * out, so we can try to allocate new block(s) to replace the bad
6130  * blocks.
6131  */
6132 static void handle_fs_bad_blocks(e2fsck_t ctx)
6133 {
6134         ext2_filsys fs = ctx->fs;
6135         dgrp_t          i;
6136         int             first_block = fs->super->s_first_data_block;
6137
6138         for (i = 0; i < fs->group_desc_count; i++) {
6139                 if (ctx->invalid_block_bitmap_flag[i]) {
6140                         new_table_block(ctx, first_block, i, _("block bitmap"),
6141                                         1, &fs->group_desc[i].bg_block_bitmap);
6142                 }
6143                 if (ctx->invalid_inode_bitmap_flag[i]) {
6144                         new_table_block(ctx, first_block, i, _("inode bitmap"),
6145                                         1, &fs->group_desc[i].bg_inode_bitmap);
6146                 }
6147                 if (ctx->invalid_inode_table_flag[i]) {
6148                         new_table_block(ctx, first_block, i, _("inode table"),
6149                                         fs->inode_blocks_per_group,
6150                                         &fs->group_desc[i].bg_inode_table);
6151                         ctx->flags |= E2F_FLAG_RESTART;
6152                 }
6153                 first_block += fs->super->s_blocks_per_group;
6154         }
6155         ctx->invalid_bitmaps = 0;
6156 }
6157
6158 /*
6159  * This routine marks all blocks which are used by the superblock,
6160  * group descriptors, inode bitmaps, and block bitmaps.
6161  */
6162 static void mark_table_blocks(e2fsck_t ctx)
6163 {
6164         ext2_filsys fs = ctx->fs;
6165         blk_t   block, b;
6166         dgrp_t  i;
6167         int     j;
6168         struct problem_context pctx;
6169
6170         clear_problem_context(&pctx);
6171
6172         block = fs->super->s_first_data_block;
6173         for (i = 0; i < fs->group_desc_count; i++) {
6174                 pctx.group = i;
6175
6176                 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
6177
6178                 /*
6179                  * Mark the blocks used for the inode table
6180                  */
6181                 if (fs->group_desc[i].bg_inode_table) {
6182                         for (j = 0, b = fs->group_desc[i].bg_inode_table;
6183                              j < fs->inode_blocks_per_group;
6184                              j++, b++) {
6185                                 if (ext2fs_test_block_bitmap(ctx->block_found_map,
6186                                                              b)) {
6187                                         pctx.blk = b;
6188                                         if (fix_problem(ctx,
6189                                                 PR_1_ITABLE_CONFLICT, &pctx)) {
6190                                                 ctx->invalid_inode_table_flag[i]++;
6191                                                 ctx->invalid_bitmaps++;
6192                                         }
6193                                 } else {
6194                                     ext2fs_mark_block_bitmap(ctx->block_found_map,
6195                                                              b);
6196                                 }
6197                         }
6198                 }
6199
6200                 /*
6201                  * Mark block used for the block bitmap
6202                  */
6203                 if (fs->group_desc[i].bg_block_bitmap) {
6204                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
6205                                      fs->group_desc[i].bg_block_bitmap)) {
6206                                 pctx.blk = fs->group_desc[i].bg_block_bitmap;
6207                                 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
6208                                         ctx->invalid_block_bitmap_flag[i]++;
6209                                         ctx->invalid_bitmaps++;
6210                                 }
6211                         } else {
6212                             ext2fs_mark_block_bitmap(ctx->block_found_map,
6213                                      fs->group_desc[i].bg_block_bitmap);
6214                     }
6215
6216                 }
6217                 /*
6218                  * Mark block used for the inode bitmap
6219                  */
6220                 if (fs->group_desc[i].bg_inode_bitmap) {
6221                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
6222                                      fs->group_desc[i].bg_inode_bitmap)) {
6223                                 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
6224                                 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
6225                                         ctx->invalid_inode_bitmap_flag[i]++;
6226                                         ctx->invalid_bitmaps++;
6227                                 }
6228                         } else {
6229                             ext2fs_mark_block_bitmap(ctx->block_found_map,
6230                                      fs->group_desc[i].bg_inode_bitmap);
6231                         }
6232                 }
6233                 block += fs->super->s_blocks_per_group;
6234         }
6235 }
6236
6237 /*
6238  * Thes subroutines short circuits ext2fs_get_blocks and
6239  * ext2fs_check_directory; we use them since we already have the inode
6240  * structure, so there's no point in letting the ext2fs library read
6241  * the inode again.
6242  */
6243 static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
6244                                   blk_t *blocks)
6245 {
6246         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6247         int     i;
6248
6249         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
6250                 return EXT2_ET_CALLBACK_NOTHANDLED;
6251
6252         for (i=0; i < EXT2_N_BLOCKS; i++)
6253                 blocks[i] = ctx->stashed_inode->i_block[i];
6254         return 0;
6255 }
6256
6257 static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
6258                                   struct ext2_inode *inode)
6259 {
6260         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6261
6262         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
6263                 return EXT2_ET_CALLBACK_NOTHANDLED;
6264         *inode = *ctx->stashed_inode;
6265         return 0;
6266 }
6267
6268 static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
6269                             struct ext2_inode *inode)
6270 {
6271         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6272
6273         if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
6274                 *ctx->stashed_inode = *inode;
6275         return EXT2_ET_CALLBACK_NOTHANDLED;
6276 }
6277
6278 static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
6279 {
6280         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6281
6282         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
6283                 return EXT2_ET_CALLBACK_NOTHANDLED;
6284
6285         if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
6286                 return EXT2_ET_NO_DIRECTORY;
6287         return 0;
6288 }
6289
6290 void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
6291 {
6292         ext2_filsys fs = ctx->fs;
6293
6294         if (bool) {
6295                 fs->get_blocks = pass1_get_blocks;
6296                 fs->check_directory = pass1_check_directory;
6297                 fs->read_inode = pass1_read_inode;
6298                 fs->write_inode = pass1_write_inode;
6299                 ctx->stashed_ino = 0;
6300         } else {
6301                 fs->get_blocks = 0;
6302                 fs->check_directory = 0;
6303                 fs->read_inode = 0;
6304                 fs->write_inode = 0;
6305         }
6306 }
6307
6308 /*
6309  * pass1b.c --- Pass #1b of e2fsck
6310  *
6311  * This file contains pass1B, pass1C, and pass1D of e2fsck.  They are
6312  * only invoked if pass 1 discovered blocks which are in use by more
6313  * than one inode.
6314  *
6315  * Pass1B scans the data blocks of all the inodes again, generating a
6316  * complete list of duplicate blocks and which inodes have claimed
6317  * them.
6318  *
6319  * Pass1C does a tree-traversal of the filesystem, to determine the
6320  * parent directories of these inodes.  This step is necessary so that
6321  * e2fsck can print out the pathnames of affected inodes.
6322  *
6323  * Pass1D is a reconciliation pass.  For each inode with duplicate
6324  * blocks, the user is prompted if s/he would like to clone the file
6325  * (so that the file gets a fresh copy of the duplicated blocks) or
6326  * simply to delete the file.
6327  *
6328  */
6329
6330
6331 /* Needed for architectures where sizeof(int) != sizeof(void *) */
6332 #define INT_TO_VOIDPTR(val)  ((void *)(intptr_t)(val))
6333 #define VOIDPTR_TO_INT(ptr)  ((int)(intptr_t)(ptr))
6334
6335 /* Define an extension to the ext2 library's block count information */
6336 #define BLOCK_COUNT_EXTATTR     (-5)
6337
6338 struct block_el {
6339         blk_t   block;
6340         struct block_el *next;
6341 };
6342
6343 struct inode_el {
6344         ext2_ino_t      inode;
6345         struct inode_el *next;
6346 };
6347
6348 struct dup_block {
6349         int             num_bad;
6350         struct inode_el *inode_list;
6351 };
6352
6353 /*
6354  * This structure stores information about a particular inode which
6355  * is sharing blocks with other inodes.  This information is collected
6356  * to display to the user, so that the user knows what files he or she
6357  * is dealing with, when trying to decide how to resolve the conflict
6358  * of multiply-claimed blocks.
6359  */
6360 struct dup_inode {
6361         ext2_ino_t              dir;
6362         int                     num_dupblocks;
6363         struct ext2_inode       inode;
6364         struct block_el         *block_list;
6365 };
6366
6367 static int process_pass1b_block(ext2_filsys fs, blk_t   *blocknr,
6368                                 e2_blkcnt_t blockcnt, blk_t ref_blk,
6369                                 int ref_offset, void *priv_data);
6370 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
6371                         struct dup_inode *dp, char *block_buf);
6372 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
6373                       struct dup_inode *dp, char* block_buf);
6374 static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
6375
6376 static void pass1b(e2fsck_t ctx, char *block_buf);
6377 static void pass1c(e2fsck_t ctx, char *block_buf);
6378 static void pass1d(e2fsck_t ctx, char *block_buf);
6379
6380 static int dup_inode_count = 0;
6381
6382 static dict_t blk_dict, ino_dict;
6383
6384 static ext2fs_inode_bitmap inode_dup_map;
6385
6386 static int dict_int_cmp(const void *a, const void *b)
6387 {
6388         intptr_t        ia, ib;
6389
6390         ia = (intptr_t)a;
6391         ib = (intptr_t)b;
6392
6393         return (ia-ib);
6394 }
6395
6396 /*
6397  * Add a duplicate block record
6398  */
6399 static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
6400                      struct ext2_inode *inode)
6401 {
6402         dnode_t *n;
6403         struct dup_block        *db;
6404         struct dup_inode        *di;
6405         struct block_el         *blk_el;
6406         struct inode_el         *ino_el;
6407
6408         n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
6409         if (n)
6410                 db = (struct dup_block *) dnode_get(n);
6411         else {
6412                 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
6413                          sizeof(struct dup_block), "duplicate block header");
6414                 db->num_bad = 0;
6415                 db->inode_list = 0;
6416                 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
6417         }
6418         ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
6419                          sizeof(struct inode_el), "inode element");
6420         ino_el->inode = ino;
6421         ino_el->next = db->inode_list;
6422         db->inode_list = ino_el;
6423         db->num_bad++;
6424
6425         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
6426         if (n)
6427                 di = (struct dup_inode *) dnode_get(n);
6428         else {
6429                 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
6430                          sizeof(struct dup_inode), "duplicate inode header");
6431                 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0 ;
6432                 di->num_dupblocks = 0;
6433                 di->block_list = 0;
6434                 di->inode = *inode;
6435                 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
6436         }
6437         blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
6438                          sizeof(struct block_el), "block element");
6439         blk_el->block = blk;
6440         blk_el->next = di->block_list;
6441         di->block_list = blk_el;
6442         di->num_dupblocks++;
6443 }
6444
6445 /*
6446  * Free a duplicate inode record
6447  */
6448 static void inode_dnode_free(dnode_t *node)
6449 {
6450         struct dup_inode        *di;
6451         struct block_el         *p, *next;
6452
6453         di = (struct dup_inode *) dnode_get(node);
6454         for (p = di->block_list; p; p = next) {
6455                 next = p->next;
6456                 free(p);
6457         }
6458         free(node);
6459 }
6460
6461 /*
6462  * Free a duplicate block record
6463  */
6464 static void block_dnode_free(dnode_t *node)
6465 {
6466         struct dup_block        *db;
6467         struct inode_el         *p, *next;
6468
6469         db = (struct dup_block *) dnode_get(node);
6470         for (p = db->inode_list; p; p = next) {
6471                 next = p->next;
6472                 free(p);
6473         }
6474         free(node);
6475 }
6476
6477
6478 /*
6479  * Main procedure for handling duplicate blocks
6480  */
6481 void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
6482 {
6483         ext2_filsys             fs = ctx->fs;
6484         struct problem_context  pctx;
6485
6486         clear_problem_context(&pctx);
6487
6488         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
6489                       _("multiply claimed inode map"), &inode_dup_map);
6490         if (pctx.errcode) {
6491                 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
6492                 ctx->flags |= E2F_FLAG_ABORT;
6493                 return;
6494         }
6495
6496         dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
6497         dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
6498         dict_set_allocator(&ino_dict, inode_dnode_free);
6499         dict_set_allocator(&blk_dict, block_dnode_free);
6500
6501         pass1b(ctx, block_buf);
6502         pass1c(ctx, block_buf);
6503         pass1d(ctx, block_buf);
6504
6505         /*
6506          * Time to free all of the accumulated data structures that we
6507          * don't need anymore.
6508          */
6509         dict_free_nodes(&ino_dict);
6510         dict_free_nodes(&blk_dict);
6511 }
6512
6513 /*
6514  * Scan the inodes looking for inodes that contain duplicate blocks.
6515  */
6516 struct process_block_struct_1b {
6517         e2fsck_t        ctx;
6518         ext2_ino_t      ino;
6519         int             dup_blocks;
6520         struct ext2_inode *inode;
6521         struct problem_context *pctx;
6522 };
6523
6524 static void pass1b(e2fsck_t ctx, char *block_buf)
6525 {
6526         ext2_filsys fs = ctx->fs;
6527         ext2_ino_t ino;
6528         struct ext2_inode inode;
6529         ext2_inode_scan scan;
6530         struct process_block_struct_1b pb;
6531         struct problem_context pctx;
6532
6533         clear_problem_context(&pctx);
6534
6535         if (!(ctx->options & E2F_OPT_PREEN))
6536                 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
6537         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
6538                                               &scan);
6539         if (pctx.errcode) {
6540                 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
6541                 ctx->flags |= E2F_FLAG_ABORT;
6542                 return;
6543         }
6544         ctx->stashed_inode = &inode;
6545         pb.ctx = ctx;
6546         pb.pctx = &pctx;
6547         pctx.str = "pass1b";
6548         while (1) {
6549                 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
6550                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
6551                         continue;
6552                 if (pctx.errcode) {
6553                         fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
6554                         ctx->flags |= E2F_FLAG_ABORT;
6555                         return;
6556                 }
6557                 if (!ino)
6558                         break;
6559                 pctx.ino = ctx->stashed_ino = ino;
6560                 if ((ino != EXT2_BAD_INO) &&
6561                     !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
6562                         continue;
6563
6564                 pb.ino = ino;
6565                 pb.dup_blocks = 0;
6566                 pb.inode = &inode;
6567
6568                 if (ext2fs_inode_has_valid_blocks(&inode) ||
6569                     (ino == EXT2_BAD_INO))
6570                         pctx.errcode = ext2fs_block_iterate2(fs, ino,
6571                                      0, block_buf, process_pass1b_block, &pb);
6572                 if (inode.i_file_acl)
6573                         process_pass1b_block(fs, &inode.i_file_acl,
6574                                              BLOCK_COUNT_EXTATTR, 0, 0, &pb);
6575                 if (pb.dup_blocks) {
6576                         end_problem_latch(ctx, PR_LATCH_DBLOCK);
6577                         if (ino >= EXT2_FIRST_INODE(fs->super) ||
6578                             ino == EXT2_ROOT_INO)
6579                                 dup_inode_count++;
6580                 }
6581                 if (pctx.errcode)
6582                         fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
6583         }
6584         ext2fs_close_inode_scan(scan);
6585         e2fsck_use_inode_shortcuts(ctx, 0);
6586 }
6587
6588 static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
6589                                 blk_t   *block_nr,
6590                                 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6591                                 blk_t ref_blk FSCK_ATTR((unused)),
6592                                 int ref_offset FSCK_ATTR((unused)),
6593                                 void *priv_data)
6594 {
6595         struct process_block_struct_1b *p;
6596         e2fsck_t ctx;
6597
6598         if (HOLE_BLKADDR(*block_nr))
6599                 return 0;
6600         p = (struct process_block_struct_1b *) priv_data;
6601         ctx = p->ctx;
6602
6603         if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
6604                 return 0;
6605
6606         /* OK, this is a duplicate block */
6607         if (p->ino != EXT2_BAD_INO) {
6608                 p->pctx->blk = *block_nr;
6609                 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
6610         }
6611         p->dup_blocks++;
6612         ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
6613
6614         add_dupe(ctx, p->ino, *block_nr, p->inode);
6615
6616         return 0;
6617 }
6618
6619 /*
6620  * Pass 1c: Scan directories for inodes with duplicate blocks.  This
6621  * is used so that we can print pathnames when prompting the user for
6622  * what to do.
6623  */
6624 struct search_dir_struct {
6625         int             count;
6626         ext2_ino_t      first_inode;
6627         ext2_ino_t      max_inode;
6628 };
6629
6630 static int search_dirent_proc(ext2_ino_t dir, int entry,
6631                               struct ext2_dir_entry *dirent,
6632                               int offset FSCK_ATTR((unused)),
6633                               int blocksize FSCK_ATTR((unused)),
6634                               char *buf FSCK_ATTR((unused)),
6635                               void *priv_data)
6636 {
6637         struct search_dir_struct *sd;
6638         struct dup_inode        *p;
6639         dnode_t                 *n;
6640
6641         sd = (struct search_dir_struct *) priv_data;
6642
6643         if (dirent->inode > sd->max_inode)
6644                 /* Should abort this inode, but not everything */
6645                 return 0;
6646
6647         if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
6648             !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
6649                 return 0;
6650
6651         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
6652         if (!n)
6653                 return 0;
6654         p = (struct dup_inode *) dnode_get(n);
6655         p->dir = dir;
6656         sd->count--;
6657
6658         return(sd->count ? 0 : DIRENT_ABORT);
6659 }
6660
6661
6662 static void pass1c(e2fsck_t ctx, char *block_buf)
6663 {
6664         ext2_filsys fs = ctx->fs;
6665         struct search_dir_struct sd;
6666         struct problem_context pctx;
6667
6668         clear_problem_context(&pctx);
6669
6670         if (!(ctx->options & E2F_OPT_PREEN))
6671                 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
6672
6673         /*
6674          * Search through all directories to translate inodes to names
6675          * (by searching for the containing directory for that inode.)
6676          */
6677         sd.count = dup_inode_count;
6678         sd.first_inode = EXT2_FIRST_INODE(fs->super);
6679         sd.max_inode = fs->super->s_inodes_count;
6680         ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
6681                                   search_dirent_proc, &sd);
6682 }
6683
6684 static void pass1d(e2fsck_t ctx, char *block_buf)
6685 {
6686         ext2_filsys fs = ctx->fs;
6687         struct dup_inode        *p, *t;
6688         struct dup_block        *q;
6689         ext2_ino_t              *shared, ino;
6690         int     shared_len;
6691         int     i;
6692         int     file_ok;
6693         int     meta_data = 0;
6694         struct problem_context pctx;
6695         dnode_t *n, *m;
6696         struct block_el *s;
6697         struct inode_el *r;
6698
6699         clear_problem_context(&pctx);
6700
6701         if (!(ctx->options & E2F_OPT_PREEN))
6702                 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
6703         e2fsck_read_bitmaps(ctx);
6704
6705         pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
6706         fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
6707         shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
6708                                 sizeof(ext2_ino_t) * dict_count(&ino_dict),
6709                                 "Shared inode list");
6710         for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
6711                 p = (struct dup_inode *) dnode_get(n);
6712                 shared_len = 0;
6713                 file_ok = 1;
6714                 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
6715                 if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
6716                         continue;
6717
6718                 /*
6719                  * Find all of the inodes which share blocks with this
6720                  * one.  First we find all of the duplicate blocks
6721                  * belonging to this inode, and then search each block
6722                  * get the list of inodes, and merge them together.
6723                  */
6724                 for (s = p->block_list; s; s = s->next) {
6725                         m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
6726                         if (!m)
6727                                 continue; /* Should never happen... */
6728                         q = (struct dup_block *) dnode_get(m);
6729                         if (q->num_bad > 1)
6730                                 file_ok = 0;
6731                         if (check_if_fs_block(ctx, s->block)) {
6732                                 file_ok = 0;
6733                                 meta_data = 1;
6734                         }
6735
6736                         /*
6737                          * Add all inodes used by this block to the
6738                          * shared[] --- which is a unique list, so
6739                          * if an inode is already in shared[], don't
6740                          * add it again.
6741                          */
6742                         for (r = q->inode_list; r; r = r->next) {
6743                                 if (r->inode == ino)
6744                                         continue;
6745                                 for (i = 0; i < shared_len; i++)
6746                                         if (shared[i] == r->inode)
6747                                                 break;
6748                                 if (i == shared_len) {
6749                                         shared[shared_len++] = r->inode;
6750                                 }
6751                         }
6752                 }
6753
6754                 /*
6755                  * Report the inode that we are working on
6756                  */
6757                 pctx.inode = &p->inode;
6758                 pctx.ino = ino;
6759                 pctx.dir = p->dir;
6760                 pctx.blkcount = p->num_dupblocks;
6761                 pctx.num = meta_data ? shared_len+1 : shared_len;
6762                 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
6763                 pctx.blkcount = 0;
6764                 pctx.num = 0;
6765
6766                 if (meta_data)
6767                         fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
6768
6769                 for (i = 0; i < shared_len; i++) {
6770                         m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
6771                         if (!m)
6772                                 continue; /* should never happen */
6773                         t = (struct dup_inode *) dnode_get(m);
6774                         /*
6775                          * Report the inode that we are sharing with
6776                          */
6777                         pctx.inode = &t->inode;
6778                         pctx.ino = shared[i];
6779                         pctx.dir = t->dir;
6780                         fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
6781                 }
6782                 if (file_ok) {
6783                         fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
6784                         continue;
6785                 }
6786                 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
6787                         pctx.errcode = clone_file(ctx, ino, p, block_buf);
6788                         if (pctx.errcode)
6789                                 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
6790                         else
6791                                 continue;
6792                 }
6793                 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
6794                         delete_file(ctx, ino, p, block_buf);
6795                 else
6796                         ext2fs_unmark_valid(fs);
6797         }
6798         ext2fs_free_mem(&shared);
6799 }
6800
6801 /*
6802  * Drop the refcount on the dup_block structure, and clear the entry
6803  * in the block_dup_map if appropriate.
6804  */
6805 static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
6806 {
6807         p->num_bad--;
6808         if (p->num_bad <= 0 ||
6809             (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
6810                 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
6811 }
6812
6813 static int delete_file_block(ext2_filsys fs,
6814                              blk_t      *block_nr,
6815                              e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6816                              blk_t ref_block FSCK_ATTR((unused)),
6817                              int ref_offset FSCK_ATTR((unused)),
6818                              void *priv_data)
6819 {
6820         struct process_block_struct_1b *pb;
6821         struct dup_block *p;
6822         dnode_t *n;
6823         e2fsck_t ctx;
6824
6825         pb = (struct process_block_struct_1b *) priv_data;
6826         ctx = pb->ctx;
6827
6828         if (HOLE_BLKADDR(*block_nr))
6829                 return 0;
6830
6831         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
6832                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
6833                 if (n) {
6834                         p = (struct dup_block *) dnode_get(n);
6835                         decrement_badcount(ctx, *block_nr, p);
6836                 } else
6837                         com_err("delete_file_block", 0,
6838                             _("internal error; can't find dup_blk for %d\n"),
6839                                 *block_nr);
6840         } else {
6841                 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6842                 ext2fs_block_alloc_stats(fs, *block_nr, -1);
6843         }
6844
6845         return 0;
6846 }
6847
6848 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
6849                         struct dup_inode *dp, char* block_buf)
6850 {
6851         ext2_filsys fs = ctx->fs;
6852         struct process_block_struct_1b pb;
6853         struct ext2_inode       inode;
6854         struct problem_context  pctx;
6855         unsigned int            count;
6856
6857         clear_problem_context(&pctx);
6858         pctx.ino = pb.ino = ino;
6859         pb.dup_blocks = dp->num_dupblocks;
6860         pb.ctx = ctx;
6861         pctx.str = "delete_file";
6862
6863         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
6864         if (ext2fs_inode_has_valid_blocks(&inode))
6865                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6866                                                      delete_file_block, &pb);
6867         if (pctx.errcode)
6868                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
6869         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6870         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6871         if (ctx->inode_bad_map)
6872                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6873         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6874
6875         /* Inode may have changed by block_iterate, so reread it */
6876         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
6877         inode.i_links_count = 0;
6878         inode.i_dtime = time(0);
6879         if (inode.i_file_acl &&
6880             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6881                 count = 1;
6882                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6883                                                    block_buf, -1, &count);
6884                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6885                         pctx.errcode = 0;
6886                         count = 1;
6887                 }
6888                 if (pctx.errcode) {
6889                         pctx.blk = inode.i_file_acl;
6890                         fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
6891                 }
6892                 /*
6893                  * If the count is zero, then arrange to have the
6894                  * block deleted.  If the block is in the block_dup_map,
6895                  * also call delete_file_block since it will take care
6896                  * of keeping the accounting straight.
6897                  */
6898                 if ((count == 0) ||
6899                     ext2fs_test_block_bitmap(ctx->block_dup_map,
6900                                              inode.i_file_acl))
6901                         delete_file_block(fs, &inode.i_file_acl,
6902                                           BLOCK_COUNT_EXTATTR, 0, 0, &pb);
6903         }
6904         e2fsck_write_inode(ctx, ino, &inode, "delete_file");
6905 }
6906
6907 struct clone_struct {
6908         errcode_t       errcode;
6909         ext2_ino_t      dir;
6910         char    *buf;
6911         e2fsck_t ctx;
6912 };
6913
6914 static int clone_file_block(ext2_filsys fs,
6915                             blk_t       *block_nr,
6916                             e2_blkcnt_t blockcnt,
6917                             blk_t ref_block FSCK_ATTR((unused)),
6918                             int ref_offset FSCK_ATTR((unused)),
6919                             void *priv_data)
6920 {
6921         struct dup_block *p;
6922         blk_t   new_block;
6923         errcode_t       retval;
6924         struct clone_struct *cs = (struct clone_struct *) priv_data;
6925         dnode_t *n;
6926         e2fsck_t ctx;
6927
6928         ctx = cs->ctx;
6929
6930         if (HOLE_BLKADDR(*block_nr))
6931                 return 0;
6932
6933         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
6934                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
6935                 if (n) {
6936                         p = (struct dup_block *) dnode_get(n);
6937                         retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
6938                                                   &new_block);
6939                         if (retval) {
6940                                 cs->errcode = retval;
6941                                 return BLOCK_ABORT;
6942                         }
6943                         if (cs->dir && (blockcnt >= 0)) {
6944                                 retval = ext2fs_set_dir_block(fs->dblist,
6945                                       cs->dir, new_block, blockcnt);
6946                                 if (retval) {
6947                                         cs->errcode = retval;
6948                                         return BLOCK_ABORT;
6949                                 }
6950                         }
6951 #if 0
6952                         printf("Cloning block %u to %u\n", *block_nr,
6953                                new_block);
6954 #endif
6955                         retval = io_channel_read_blk(fs->io, *block_nr, 1,
6956                                                      cs->buf);
6957                         if (retval) {
6958                                 cs->errcode = retval;
6959                                 return BLOCK_ABORT;
6960                         }
6961                         retval = io_channel_write_blk(fs->io, new_block, 1,
6962                                                       cs->buf);
6963                         if (retval) {
6964                                 cs->errcode = retval;
6965                                 return BLOCK_ABORT;
6966                         }
6967                         decrement_badcount(ctx, *block_nr, p);
6968                         *block_nr = new_block;
6969                         ext2fs_mark_block_bitmap(ctx->block_found_map,
6970                                                  new_block);
6971                         ext2fs_mark_block_bitmap(fs->block_map, new_block);
6972                         return BLOCK_CHANGED;
6973                 } else
6974                         com_err("clone_file_block", 0,
6975                             _("internal error; can't find dup_blk for %d\n"),
6976                                 *block_nr);
6977         }
6978         return 0;
6979 }
6980
6981 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
6982                       struct dup_inode *dp, char* block_buf)
6983 {
6984         ext2_filsys fs = ctx->fs;
6985         errcode_t       retval;
6986         struct clone_struct cs;
6987         struct problem_context  pctx;
6988         blk_t           blk;
6989         dnode_t         *n;
6990         struct inode_el *ino_el;
6991         struct dup_block        *db;
6992         struct dup_inode        *di;
6993
6994         clear_problem_context(&pctx);
6995         cs.errcode = 0;
6996         cs.dir = 0;
6997         cs.ctx = ctx;
6998         retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
6999         if (retval)
7000                 return retval;
7001
7002         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
7003                 cs.dir = ino;
7004
7005         pctx.ino = ino;
7006         pctx.str = "clone_file";
7007         if (ext2fs_inode_has_valid_blocks(&dp->inode))
7008                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
7009                                                      clone_file_block, &cs);
7010         ext2fs_mark_bb_dirty(fs);
7011         if (pctx.errcode) {
7012                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
7013                 retval = pctx.errcode;
7014                 goto errout;
7015         }
7016         if (cs.errcode) {
7017                 com_err("clone_file", cs.errcode,
7018                         _("returned from clone_file_block"));
7019                 retval = cs.errcode;
7020                 goto errout;
7021         }
7022         /* The inode may have changed on disk, so we have to re-read it */
7023         e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
7024         blk = dp->inode.i_file_acl;
7025         if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
7026                                      BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
7027                     BLOCK_CHANGED)) {
7028                 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
7029                 /*
7030                  * If we cloned the EA block, find all other inodes
7031                  * which refered to that EA block, and modify
7032                  * them to point to the new EA block.
7033                  */
7034                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
7035                 db = (struct dup_block *) dnode_get(n);
7036                 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
7037                         if (ino_el->inode == ino)
7038                                 continue;
7039                         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
7040                         di = (struct dup_inode *) dnode_get(n);
7041                         if (di->inode.i_file_acl == blk) {
7042                                 di->inode.i_file_acl = dp->inode.i_file_acl;
7043                                 e2fsck_write_inode(ctx, ino_el->inode,
7044                                            &di->inode, "clone file EA");
7045                                 decrement_badcount(ctx, blk, db);
7046                         }
7047                 }
7048         }
7049         retval = 0;
7050 errout:
7051         ext2fs_free_mem(&cs.buf);
7052         return retval;
7053 }
7054
7055 /*
7056  * This routine returns 1 if a block overlaps with one of the superblocks,
7057  * group descriptors, inode bitmaps, or block bitmaps.
7058  */
7059 static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
7060 {
7061         ext2_filsys fs = ctx->fs;
7062         blk_t   block;
7063         dgrp_t  i;
7064
7065         block = fs->super->s_first_data_block;
7066         for (i = 0; i < fs->group_desc_count; i++) {
7067
7068                 /* Check superblocks/block group descriptros */
7069                 if (ext2fs_bg_has_super(fs, i)) {
7070                         if (test_block >= block &&
7071                             (test_block <= block + fs->desc_blocks))
7072                                 return 1;
7073                 }
7074
7075                 /* Check the inode table */
7076                 if ((fs->group_desc[i].bg_inode_table) &&
7077                     (test_block >= fs->group_desc[i].bg_inode_table) &&
7078                     (test_block < (fs->group_desc[i].bg_inode_table +
7079                                    fs->inode_blocks_per_group)))
7080                         return 1;
7081
7082                 /* Check the bitmap blocks */
7083                 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
7084                     (test_block == fs->group_desc[i].bg_inode_bitmap))
7085                         return 1;
7086
7087                 block += fs->super->s_blocks_per_group;
7088         }
7089         return 0;
7090 }
7091 /*
7092  * pass2.c --- check directory structure
7093  *
7094  * Pass 2 of e2fsck iterates through all active directory inodes, and
7095  * applies to following tests to each directory entry in the directory
7096  * blocks in the inodes:
7097  *
7098  *      - The length of the directory entry (rec_len) should be at
7099  *              least 8 bytes, and no more than the remaining space
7100  *              left in the directory block.
7101  *      - The length of the name in the directory entry (name_len)
7102  *              should be less than (rec_len - 8).
7103  *      - The inode number in the directory entry should be within
7104  *              legal bounds.
7105  *      - The inode number should refer to a in-use inode.
7106  *      - The first entry should be '.', and its inode should be
7107  *              the inode of the directory.
7108  *      - The second entry should be '..'.
7109  *
7110  * To minimize disk seek time, the directory blocks are processed in
7111  * sorted order of block numbers.
7112  *
7113  * Pass 2 also collects the following information:
7114  *      - The inode numbers of the subdirectories for each directory.
7115  *
7116  * Pass 2 relies on the following information from previous passes:
7117  *      - The directory information collected in pass 1.
7118  *      - The inode_used_map bitmap
7119  *      - The inode_bad_map bitmap
7120  *      - The inode_dir_map bitmap
7121  *
7122  * Pass 2 frees the following data structures
7123  *      - The inode_bad_map bitmap
7124  *      - The inode_reg_map bitmap
7125  */
7126
7127 /* #define DX_DEBUG */
7128
7129 /*
7130  * Keeps track of how many times an inode is referenced.
7131  */
7132 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
7133 static int check_dir_block(ext2_filsys fs,
7134                            struct ext2_db_entry *dir_blocks_info,
7135                            void *priv_data);
7136 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
7137                               struct problem_context *pctx);
7138 static int update_dir_block(ext2_filsys fs,
7139                             blk_t       *block_nr,
7140                             e2_blkcnt_t blockcnt,
7141                             blk_t       ref_block,
7142                             int         ref_offset,
7143                             void        *priv_data);
7144 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
7145 static int htree_depth(struct dx_dir_info *dx_dir,
7146                        struct dx_dirblock_info *dx_db);
7147 static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b);
7148
7149 struct check_dir_struct {
7150         char *buf;
7151         struct problem_context  pctx;
7152         int     count, max;
7153         e2fsck_t ctx;
7154 };
7155
7156 static void e2fsck_pass2(e2fsck_t ctx)
7157 {
7158         struct ext2_super_block *sb = ctx->fs->super;
7159         struct problem_context  pctx;
7160         ext2_filsys             fs = ctx->fs;
7161         char                    *buf;
7162 #ifdef RESOURCE_TRACK
7163         struct resource_track   rtrack;
7164 #endif
7165         struct dir_info         *dir;
7166         struct check_dir_struct cd;
7167         struct dx_dir_info      *dx_dir;
7168         struct dx_dirblock_info *dx_db, *dx_parent;
7169         int                     b;
7170         int                     i, depth;
7171         problem_t               code;
7172         int                     bad_dir;
7173
7174 #ifdef RESOURCE_TRACK
7175         init_resource_track(&rtrack);
7176 #endif
7177
7178         clear_problem_context(&cd.pctx);
7179
7180 #ifdef MTRACE
7181         mtrace_print("Pass 2");
7182 #endif
7183
7184         if (!(ctx->options & E2F_OPT_PREEN))
7185                 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
7186
7187         cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
7188                                                 0, ctx->inode_link_info,
7189                                                 &ctx->inode_count);
7190         if (cd.pctx.errcode) {
7191                 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
7192                 ctx->flags |= E2F_FLAG_ABORT;
7193                 return;
7194         }
7195         buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
7196                                               "directory scan buffer");
7197
7198         /*
7199          * Set up the parent pointer for the root directory, if
7200          * present.  (If the root directory is not present, we will
7201          * create it in pass 3.)
7202          */
7203         dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
7204         if (dir)
7205                 dir->parent = EXT2_ROOT_INO;
7206
7207         cd.buf = buf;
7208         cd.ctx = ctx;
7209         cd.count = 1;
7210         cd.max = ext2fs_dblist_count(fs->dblist);
7211
7212         if (ctx->progress)
7213                 (void) (ctx->progress)(ctx, 2, 0, cd.max);
7214
7215         if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
7216                 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
7217
7218         cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
7219                                                 &cd);
7220         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7221                 return;
7222         if (cd.pctx.errcode) {
7223                 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
7224                 ctx->flags |= E2F_FLAG_ABORT;
7225                 return;
7226         }
7227
7228 #ifdef ENABLE_HTREE
7229         for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
7230                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7231                         return;
7232                 if (dx_dir->numblocks == 0)
7233                         continue;
7234                 clear_problem_context(&pctx);
7235                 bad_dir = 0;
7236                 pctx.dir = dx_dir->ino;
7237                 dx_db = dx_dir->dx_block;
7238                 if (dx_db->flags & DX_FLAG_REFERENCED)
7239                         dx_db->flags |= DX_FLAG_DUP_REF;
7240                 else
7241                         dx_db->flags |= DX_FLAG_REFERENCED;
7242                 /*
7243                  * Find all of the first and last leaf blocks, and
7244                  * update their parent's min and max hash values
7245                  */
7246                 for (b=0, dx_db = dx_dir->dx_block;
7247                      b < dx_dir->numblocks;
7248                      b++, dx_db++) {
7249                         if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
7250                             !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
7251                                 continue;
7252                         dx_parent = &dx_dir->dx_block[dx_db->parent];
7253                         /*
7254                          * XXX Make sure dx_parent->min_hash > dx_db->min_hash
7255                          */
7256                         if (dx_db->flags & DX_FLAG_FIRST)
7257                                 dx_parent->min_hash = dx_db->min_hash;
7258                         /*
7259                          * XXX Make sure dx_parent->max_hash < dx_db->max_hash
7260                          */
7261                         if (dx_db->flags & DX_FLAG_LAST)
7262                                 dx_parent->max_hash = dx_db->max_hash;
7263                 }
7264
7265                 for (b=0, dx_db = dx_dir->dx_block;
7266                      b < dx_dir->numblocks;
7267                      b++, dx_db++) {
7268                         pctx.blkcount = b;
7269                         pctx.group = dx_db->parent;
7270                         code = 0;
7271                         if (!(dx_db->flags & DX_FLAG_FIRST) &&
7272                             (dx_db->min_hash < dx_db->node_min_hash)) {
7273                                 pctx.blk = dx_db->min_hash;
7274                                 pctx.blk2 = dx_db->node_min_hash;
7275                                 code = PR_2_HTREE_MIN_HASH;
7276                                 fix_problem(ctx, code, &pctx);
7277                                 bad_dir++;
7278                         }
7279                         if (dx_db->type == DX_DIRBLOCK_LEAF) {
7280                                 depth = htree_depth(dx_dir, dx_db);
7281                                 if (depth != dx_dir->depth) {
7282                                         code = PR_2_HTREE_BAD_DEPTH;
7283                                         fix_problem(ctx, code, &pctx);
7284                                         bad_dir++;
7285                                 }
7286                         }
7287                         /*
7288                          * This test doesn't apply for the root block
7289                          * at block #0
7290                          */
7291                         if (b &&
7292                             (dx_db->max_hash > dx_db->node_max_hash)) {
7293                                 pctx.blk = dx_db->max_hash;
7294                                 pctx.blk2 = dx_db->node_max_hash;
7295                                 code = PR_2_HTREE_MAX_HASH;
7296                                 fix_problem(ctx, code, &pctx);
7297                                 bad_dir++;
7298                         }
7299                         if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
7300                                 code = PR_2_HTREE_NOTREF;
7301                                 fix_problem(ctx, code, &pctx);
7302                                 bad_dir++;
7303                         } else if (dx_db->flags & DX_FLAG_DUP_REF) {
7304                                 code = PR_2_HTREE_DUPREF;
7305                                 fix_problem(ctx, code, &pctx);
7306                                 bad_dir++;
7307                         }
7308                         if (code == 0)
7309                                 continue;
7310                 }
7311                 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
7312                         clear_htree(ctx, dx_dir->ino);
7313                         dx_dir->numblocks = 0;
7314                 }
7315         }
7316 #endif
7317         ext2fs_free_mem(&buf);
7318         ext2fs_free_dblist(fs->dblist);
7319
7320         ext2fs_free_inode_bitmap(ctx->inode_bad_map);
7321         ctx->inode_bad_map = 0;
7322         ext2fs_free_inode_bitmap(ctx->inode_reg_map);
7323         ctx->inode_reg_map = 0;
7324
7325         clear_problem_context(&pctx);
7326         if (ctx->large_files) {
7327                 if (!(sb->s_feature_ro_compat &
7328                       EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
7329                     fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
7330                         sb->s_feature_ro_compat |=
7331                                 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
7332                         ext2fs_mark_super_dirty(fs);
7333                 }
7334                 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
7335                     fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
7336                         ext2fs_update_dynamic_rev(fs);
7337                         ext2fs_mark_super_dirty(fs);
7338                 }
7339         } else if (!ctx->large_files &&
7340             (sb->s_feature_ro_compat &
7341               EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
7342                 if (fs->flags & EXT2_FLAG_RW) {
7343                         sb->s_feature_ro_compat &=
7344                                 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
7345                         ext2fs_mark_super_dirty(fs);
7346                 }
7347         }
7348
7349 #ifdef RESOURCE_TRACK
7350         if (ctx->options & E2F_OPT_TIME2) {
7351                 e2fsck_clear_progbar(ctx);
7352                 print_resource_track(_("Pass 2"), &rtrack);
7353         }
7354 #endif
7355 }
7356
7357 #define MAX_DEPTH 32000
7358 static int htree_depth(struct dx_dir_info *dx_dir,
7359                        struct dx_dirblock_info *dx_db)
7360 {
7361         int     depth = 0;
7362
7363         while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
7364                 dx_db = &dx_dir->dx_block[dx_db->parent];
7365                 depth++;
7366         }
7367         return depth;
7368 }
7369
7370 static int dict_de_cmp(const void *a, const void *b)
7371 {
7372         const struct ext2_dir_entry *de_a, *de_b;
7373         int     a_len, b_len;
7374
7375         de_a = (const struct ext2_dir_entry *) a;
7376         a_len = de_a->name_len & 0xFF;
7377         de_b = (const struct ext2_dir_entry *) b;
7378         b_len = de_b->name_len & 0xFF;
7379
7380         if (a_len != b_len)
7381                 return (a_len - b_len);
7382
7383         return strncmp(de_a->name, de_b->name, a_len);
7384 }
7385
7386 /*
7387  * This is special sort function that makes sure that directory blocks
7388  * with a dirblock of zero are sorted to the beginning of the list.
7389  * This guarantees that the root node of the htree directories are
7390  * processed first, so we know what hash version to use.
7391  */
7392 static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b)
7393 {
7394         const struct ext2_db_entry *db_a =
7395                 (const struct ext2_db_entry *) a;
7396         const struct ext2_db_entry *db_b =
7397                 (const struct ext2_db_entry *) b;
7398
7399         if (db_a->blockcnt && !db_b->blockcnt)
7400                 return 1;
7401
7402         if (!db_a->blockcnt && db_b->blockcnt)
7403                 return -1;
7404
7405         if (db_a->blk != db_b->blk)
7406                 return (int) (db_a->blk - db_b->blk);
7407
7408         if (db_a->ino != db_b->ino)
7409                 return (int) (db_a->ino - db_b->ino);
7410
7411         return (int) (db_a->blockcnt - db_b->blockcnt);
7412 }
7413
7414
7415 /*
7416  * Make sure the first entry in the directory is '.', and that the
7417  * directory entry is sane.
7418  */
7419 static int check_dot(e2fsck_t ctx,
7420                      struct ext2_dir_entry *dirent,
7421                      ext2_ino_t ino, struct problem_context *pctx)
7422 {
7423         struct ext2_dir_entry *nextdir;
7424         int     status = 0;
7425         int     created = 0;
7426         int     new_len;
7427         int     problem = 0;
7428
7429         if (!dirent->inode)
7430                 problem = PR_2_MISSING_DOT;
7431         else if (((dirent->name_len & 0xFF) != 1) ||
7432                  (dirent->name[0] != '.'))
7433                 problem = PR_2_1ST_NOT_DOT;
7434         else if (dirent->name[1] != '\0')
7435                 problem = PR_2_DOT_NULL_TERM;
7436
7437         if (problem) {
7438                 if (fix_problem(ctx, problem, pctx)) {
7439                         if (dirent->rec_len < 12)
7440                                 dirent->rec_len = 12;
7441                         dirent->inode = ino;
7442                         dirent->name_len = 1;
7443                         dirent->name[0] = '.';
7444                         dirent->name[1] = '\0';
7445                         status = 1;
7446                         created = 1;
7447                 }
7448         }
7449         if (dirent->inode != ino) {
7450                 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
7451                         dirent->inode = ino;
7452                         status = 1;
7453                 }
7454         }
7455         if (dirent->rec_len > 12) {
7456                 new_len = dirent->rec_len - 12;
7457                 if (new_len > 12) {
7458                         if (created ||
7459                             fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
7460                                 nextdir = (struct ext2_dir_entry *)
7461                                         ((char *) dirent + 12);
7462                                 dirent->rec_len = 12;
7463                                 nextdir->rec_len = new_len;
7464                                 nextdir->inode = 0;
7465                                 nextdir->name_len = 0;
7466                                 status = 1;
7467                         }
7468                 }
7469         }
7470         return status;
7471 }
7472
7473 /*
7474  * Make sure the second entry in the directory is '..', and that the
7475  * directory entry is sane.  We do not check the inode number of '..'
7476  * here; this gets done in pass 3.
7477  */
7478 static int check_dotdot(e2fsck_t ctx,
7479                         struct ext2_dir_entry *dirent,
7480                         struct dir_info *dir, struct problem_context *pctx)
7481 {
7482         int             problem = 0;
7483
7484         if (!dirent->inode)
7485                 problem = PR_2_MISSING_DOT_DOT;
7486         else if (((dirent->name_len & 0xFF) != 2) ||
7487                  (dirent->name[0] != '.') ||
7488                  (dirent->name[1] != '.'))
7489                 problem = PR_2_2ND_NOT_DOT_DOT;
7490         else if (dirent->name[2] != '\0')
7491                 problem = PR_2_DOT_DOT_NULL_TERM;
7492
7493         if (problem) {
7494                 if (fix_problem(ctx, problem, pctx)) {
7495                         if (dirent->rec_len < 12)
7496                                 dirent->rec_len = 12;
7497                         /*
7498                          * Note: we don't have the parent inode just
7499                          * yet, so we will fill it in with the root
7500                          * inode.  This will get fixed in pass 3.
7501                          */
7502                         dirent->inode = EXT2_ROOT_INO;
7503                         dirent->name_len = 2;
7504                         dirent->name[0] = '.';
7505                         dirent->name[1] = '.';
7506                         dirent->name[2] = '\0';
7507                         return 1;
7508                 }
7509                 return 0;
7510         }
7511         dir->dotdot = dirent->inode;
7512         return 0;
7513 }
7514
7515 /*
7516  * Check to make sure a directory entry doesn't contain any illegal
7517  * characters.
7518  */
7519 static int check_name(e2fsck_t ctx,
7520                       struct ext2_dir_entry *dirent,
7521                       struct problem_context *pctx)
7522 {
7523         int     i;
7524         int     fixup = -1;
7525         int     ret = 0;
7526
7527         for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
7528                 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
7529                         if (fixup < 0) {
7530                                 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
7531                         }
7532                         if (fixup) {
7533                                 dirent->name[i] = '.';
7534                                 ret = 1;
7535                         }
7536                 }
7537         }
7538         return ret;
7539 }
7540
7541 /*
7542  * Check the directory filetype (if present)
7543  */
7544
7545 /*
7546  * Given a mode, return the ext2 file type
7547  */
7548 static int ext2_file_type(unsigned int mode)
7549 {
7550         if (LINUX_S_ISREG(mode))
7551                 return EXT2_FT_REG_FILE;
7552
7553         if (LINUX_S_ISDIR(mode))
7554                 return EXT2_FT_DIR;
7555
7556         if (LINUX_S_ISCHR(mode))
7557                 return EXT2_FT_CHRDEV;
7558
7559         if (LINUX_S_ISBLK(mode))
7560                 return EXT2_FT_BLKDEV;
7561
7562         if (LINUX_S_ISLNK(mode))
7563                 return EXT2_FT_SYMLINK;
7564
7565         if (LINUX_S_ISFIFO(mode))
7566                 return EXT2_FT_FIFO;
7567
7568         if (LINUX_S_ISSOCK(mode))
7569                 return EXT2_FT_SOCK;
7570
7571         return 0;
7572 }
7573
7574 static _INLINE_ int check_filetype(e2fsck_t ctx,
7575                                    struct ext2_dir_entry *dirent,
7576                                    struct problem_context *pctx)
7577 {
7578         int     filetype = dirent->name_len >> 8;
7579         int     should_be = EXT2_FT_UNKNOWN;
7580         struct ext2_inode       inode;
7581
7582         if (!(ctx->fs->super->s_feature_incompat &
7583               EXT2_FEATURE_INCOMPAT_FILETYPE)) {
7584                 if (filetype == 0 ||
7585                     !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
7586                         return 0;
7587                 dirent->name_len = dirent->name_len & 0xFF;
7588                 return 1;
7589         }
7590
7591         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
7592                 should_be = EXT2_FT_DIR;
7593         } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
7594                                             dirent->inode)) {
7595                 should_be = EXT2_FT_REG_FILE;
7596         } else if (ctx->inode_bad_map &&
7597                    ext2fs_test_inode_bitmap(ctx->inode_bad_map,
7598                                             dirent->inode))
7599                 should_be = 0;
7600         else {
7601                 e2fsck_read_inode(ctx, dirent->inode, &inode,
7602                                   "check_filetype");
7603                 should_be = ext2_file_type(inode.i_mode);
7604         }
7605         if (filetype == should_be)
7606                 return 0;
7607         pctx->num = should_be;
7608
7609         if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
7610                         pctx) == 0)
7611                 return 0;
7612
7613         dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
7614         return 1;
7615 }
7616
7617 #ifdef ENABLE_HTREE
7618 static void parse_int_node(ext2_filsys fs,
7619                            struct ext2_db_entry *db,
7620                            struct check_dir_struct *cd,
7621                            struct dx_dir_info   *dx_dir,
7622                            char *block_buf)
7623 {
7624         struct          ext2_dx_root_info  *root;
7625         struct          ext2_dx_entry *ent;
7626         struct          ext2_dx_countlimit *limit;
7627         struct dx_dirblock_info *dx_db;
7628         int             i, expect_limit, count;
7629         blk_t           blk;
7630         ext2_dirhash_t  min_hash = 0xffffffff;
7631         ext2_dirhash_t  max_hash = 0;
7632         ext2_dirhash_t  hash = 0, prev_hash;
7633
7634         if (db->blockcnt == 0) {
7635                 root = (struct ext2_dx_root_info *) (block_buf + 24);
7636
7637 #ifdef DX_DEBUG
7638                 printf("Root node dump:\n");
7639                 printf("\t Reserved zero: %d\n", root->reserved_zero);
7640                 printf("\t Hash Version: %d\n", root->hash_version);
7641                 printf("\t Info length: %d\n", root->info_length);
7642                 printf("\t Indirect levels: %d\n", root->indirect_levels);
7643                 printf("\t Flags: %d\n", root->unused_flags);
7644 #endif
7645
7646                 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
7647         } else {
7648                 ent = (struct ext2_dx_entry *) (block_buf+8);
7649         }
7650         limit = (struct ext2_dx_countlimit *) ent;
7651
7652 #ifdef DX_DEBUG
7653         printf("Number of entries (count): %d\n",
7654                ext2fs_le16_to_cpu(limit->count));
7655         printf("Number of entries (limit): %d\n",
7656                ext2fs_le16_to_cpu(limit->limit));
7657 #endif
7658
7659         count = ext2fs_le16_to_cpu(limit->count);
7660         expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
7661                 sizeof(struct ext2_dx_entry);
7662         if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
7663                 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
7664                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
7665                         goto clear_and_exit;
7666         }
7667         if (count > expect_limit) {
7668                 cd->pctx.num = count;
7669                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
7670                         goto clear_and_exit;
7671                 count = expect_limit;
7672         }
7673
7674         for (i=0; i < count; i++) {
7675                 prev_hash = hash;
7676                 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
7677 #ifdef DX_DEBUG
7678                 printf("Entry #%d: Hash 0x%08x, block %d\n", i,
7679                        hash, ext2fs_le32_to_cpu(ent[i].block));
7680 #endif
7681                 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
7682                 /* Check to make sure the block is valid */
7683                 if (blk > (blk_t) dx_dir->numblocks) {
7684                         cd->pctx.blk = blk;
7685                         if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
7686                                         &cd->pctx))
7687                                 goto clear_and_exit;
7688                 }
7689                 if (hash < prev_hash &&
7690                     fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
7691                         goto clear_and_exit;
7692                 dx_db = &dx_dir->dx_block[blk];
7693                 if (dx_db->flags & DX_FLAG_REFERENCED) {
7694                         dx_db->flags |= DX_FLAG_DUP_REF;
7695                 } else {
7696                         dx_db->flags |= DX_FLAG_REFERENCED;
7697                         dx_db->parent = db->blockcnt;
7698                 }
7699                 if (hash < min_hash)
7700                         min_hash = hash;
7701                 if (hash > max_hash)
7702                         max_hash = hash;
7703                 dx_db->node_min_hash = hash;
7704                 if ((i+1) < count)
7705                         dx_db->node_max_hash =
7706                           ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
7707                 else {
7708                         dx_db->node_max_hash = 0xfffffffe;
7709                         dx_db->flags |= DX_FLAG_LAST;
7710                 }
7711                 if (i == 0)
7712                         dx_db->flags |= DX_FLAG_FIRST;
7713         }
7714 #ifdef DX_DEBUG
7715         printf("Blockcnt = %d, min hash 0x%08x, max hash 0x%08x\n",
7716                db->blockcnt, min_hash, max_hash);
7717 #endif
7718         dx_db = &dx_dir->dx_block[db->blockcnt];
7719         dx_db->min_hash = min_hash;
7720         dx_db->max_hash = max_hash;
7721         return;
7722
7723 clear_and_exit:
7724         clear_htree(cd->ctx, cd->pctx.ino);
7725         dx_dir->numblocks = 0;
7726 }
7727 #endif /* ENABLE_HTREE */
7728
7729 /*
7730  * Given a busted directory, try to salvage it somehow.
7731  *
7732  */
7733 static void salvage_directory(ext2_filsys fs,
7734                               struct ext2_dir_entry *dirent,
7735                               struct ext2_dir_entry *prev,
7736                               unsigned int *offset)
7737 {
7738         char    *cp = (char *) dirent;
7739         int left = fs->blocksize - *offset - dirent->rec_len;
7740         int name_len = dirent->name_len & 0xFF;
7741
7742         /*
7743          * Special case of directory entry of size 8: copy what's left
7744          * of the directory block up to cover up the invalid hole.
7745          */
7746         if ((left >= 12) && (dirent->rec_len == 8)) {
7747                 memmove(cp, cp+8, left);
7748                 memset(cp + left, 0, 8);
7749                 return;
7750         }
7751         /*
7752          * If the directory entry overruns the end of the directory
7753          * block, and the name is small enough to fit, then adjust the
7754          * record length.
7755          */
7756         if ((left < 0) &&
7757             (name_len + 8 <= dirent->rec_len + left) &&
7758             dirent->inode <= fs->super->s_inodes_count &&
7759             strnlen(dirent->name, name_len) == name_len) {
7760                 dirent->rec_len += left;
7761                 return;
7762         }
7763         /*
7764          * If the directory entry is a multiple of four, so it is
7765          * valid, let the previous directory entry absorb the invalid
7766          * one.
7767          */
7768         if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
7769                 prev->rec_len += dirent->rec_len;
7770                 *offset += dirent->rec_len;
7771                 return;
7772         }
7773         /*
7774          * Default salvage method --- kill all of the directory
7775          * entries for the rest of the block.  We will either try to
7776          * absorb it into the previous directory entry, or create a
7777          * new empty directory entry the rest of the directory block.
7778          */
7779         if (prev) {
7780                 prev->rec_len += fs->blocksize - *offset;
7781                 *offset = fs->blocksize;
7782         } else {
7783                 dirent->rec_len = fs->blocksize - *offset;
7784                 dirent->name_len = 0;
7785                 dirent->inode = 0;
7786         }
7787 }
7788
7789 static int check_dir_block(ext2_filsys fs,
7790                            struct ext2_db_entry *db,
7791                            void *priv_data)
7792 {
7793         struct dir_info         *subdir, *dir;
7794         struct dx_dir_info      *dx_dir;
7795 #ifdef ENABLE_HTREE
7796         struct dx_dirblock_info *dx_db = 0;
7797 #endif /* ENABLE_HTREE */
7798         struct ext2_dir_entry   *dirent, *prev;
7799         ext2_dirhash_t          hash;
7800         unsigned int            offset = 0;
7801         int                     dir_modified = 0;
7802         int                     dot_state;
7803         blk_t                   block_nr = db->blk;
7804         ext2_ino_t              ino = db->ino;
7805         __u16                   links;
7806         struct check_dir_struct *cd;
7807         char                    *buf;
7808         e2fsck_t                ctx;
7809         int                     problem;
7810         struct ext2_dx_root_info *root;
7811         struct ext2_dx_countlimit *limit;
7812         static dict_t de_dict;
7813         struct problem_context  pctx;
7814         int     dups_found = 0;
7815
7816         cd = (struct check_dir_struct *) priv_data;
7817         buf = cd->buf;
7818         ctx = cd->ctx;
7819
7820         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7821                 return DIRENT_ABORT;
7822
7823         if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
7824                 return DIRENT_ABORT;
7825
7826         /*
7827          * Make sure the inode is still in use (could have been
7828          * deleted in the duplicate/bad blocks pass.
7829          */
7830         if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
7831                 return 0;
7832
7833         cd->pctx.ino = ino;
7834         cd->pctx.blk = block_nr;
7835         cd->pctx.blkcount = db->blockcnt;
7836         cd->pctx.ino2 = 0;
7837         cd->pctx.dirent = 0;
7838         cd->pctx.num = 0;
7839
7840         if (db->blk == 0) {
7841                 if (allocate_dir_block(ctx, db, &cd->pctx))
7842                         return 0;
7843                 block_nr = db->blk;
7844         }
7845
7846         if (db->blockcnt)
7847                 dot_state = 2;
7848         else
7849                 dot_state = 0;
7850
7851         if (ctx->dirs_to_hash &&
7852             ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
7853                 dups_found++;
7854
7855 #if 0
7856         printf("In process_dir_block block %lu, #%d, inode %lu\n", block_nr,
7857                db->blockcnt, ino);
7858 #endif
7859
7860         cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
7861         if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
7862                 cd->pctx.errcode = 0; /* We'll handle this ourselves */
7863         if (cd->pctx.errcode) {
7864                 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
7865                         ctx->flags |= E2F_FLAG_ABORT;
7866                         return DIRENT_ABORT;
7867                 }
7868                 memset(buf, 0, fs->blocksize);
7869         }
7870 #ifdef ENABLE_HTREE
7871         dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
7872         if (dx_dir && dx_dir->numblocks) {
7873                 if (db->blockcnt >= dx_dir->numblocks) {
7874                         printf("XXX should never happen!!!\n");
7875                         abort();
7876                 }
7877                 dx_db = &dx_dir->dx_block[db->blockcnt];
7878                 dx_db->type = DX_DIRBLOCK_LEAF;
7879                 dx_db->phys = block_nr;
7880                 dx_db->min_hash = ~0;
7881                 dx_db->max_hash = 0;
7882
7883                 dirent = (struct ext2_dir_entry *) buf;
7884                 limit = (struct ext2_dx_countlimit *) (buf+8);
7885                 if (db->blockcnt == 0) {
7886                         root = (struct ext2_dx_root_info *) (buf + 24);
7887                         dx_db->type = DX_DIRBLOCK_ROOT;
7888                         dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
7889                         if ((root->reserved_zero ||
7890                              root->info_length < 8 ||
7891                              root->indirect_levels > 1) &&
7892                             fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
7893                                 clear_htree(ctx, ino);
7894                                 dx_dir->numblocks = 0;
7895                                 dx_db = 0;
7896                         }
7897                         dx_dir->hashversion = root->hash_version;
7898                         dx_dir->depth = root->indirect_levels + 1;
7899                 } else if ((dirent->inode == 0) &&
7900                            (dirent->rec_len == fs->blocksize) &&
7901                            (dirent->name_len == 0) &&
7902                            (ext2fs_le16_to_cpu(limit->limit) ==
7903                             ((fs->blocksize-8) /
7904                              sizeof(struct ext2_dx_entry))))
7905                         dx_db->type = DX_DIRBLOCK_NODE;
7906         }
7907 #endif /* ENABLE_HTREE */
7908
7909         dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
7910         prev = 0;
7911         do {
7912                 problem = 0;
7913                 dirent = (struct ext2_dir_entry *) (buf + offset);
7914                 cd->pctx.dirent = dirent;
7915                 cd->pctx.num = offset;
7916                 if (((offset + dirent->rec_len) > fs->blocksize) ||
7917                     (dirent->rec_len < 12) ||
7918                     ((dirent->rec_len % 4) != 0) ||
7919                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
7920                         if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
7921                                 salvage_directory(fs, dirent, prev, &offset);
7922                                 dir_modified++;
7923                                 continue;
7924                         } else
7925                                 goto abort_free_dict;
7926                 }
7927                 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
7928                         if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
7929                                 dirent->name_len = EXT2_NAME_LEN;
7930                                 dir_modified++;
7931                         }
7932                 }
7933
7934                 if (dot_state == 0) {
7935                         if (check_dot(ctx, dirent, ino, &cd->pctx))
7936                                 dir_modified++;
7937                 } else if (dot_state == 1) {
7938                         dir = e2fsck_get_dir_info(ctx, ino);
7939                         if (!dir) {
7940                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
7941                                 goto abort_free_dict;
7942                         }
7943                         if (check_dotdot(ctx, dirent, dir, &cd->pctx))
7944                                 dir_modified++;
7945                 } else if (dirent->inode == ino) {
7946                         problem = PR_2_LINK_DOT;
7947                         if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
7948                                 dirent->inode = 0;
7949                                 dir_modified++;
7950                                 goto next;
7951                         }
7952                 }
7953                 if (!dirent->inode)
7954                         goto next;
7955
7956                 /*
7957                  * Make sure the inode listed is a legal one.
7958                  */
7959                 if (((dirent->inode != EXT2_ROOT_INO) &&
7960                      (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
7961                     (dirent->inode > fs->super->s_inodes_count)) {
7962                         problem = PR_2_BAD_INO;
7963                 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
7964                                                dirent->inode))) {
7965                         /*
7966                          * If the inode is unused, offer to clear it.
7967                          */
7968                         problem = PR_2_UNUSED_INODE;
7969                 } else if (ctx->inode_bb_map &&
7970                            (ext2fs_test_inode_bitmap(ctx->inode_bb_map,
7971                                                      dirent->inode))) {
7972                         /*
7973                          * If the inode is in a bad block, offer to
7974                          * clear it.
7975                          */
7976                         problem = PR_2_BB_INODE;
7977                 } else if ((dot_state > 1) &&
7978                            ((dirent->name_len & 0xFF) == 1) &&
7979                            (dirent->name[0] == '.')) {
7980                         /*
7981                          * If there's a '.' entry in anything other
7982                          * than the first directory entry, it's a
7983                          * duplicate entry that should be removed.
7984                          */
7985                         problem = PR_2_DUP_DOT;
7986                 } else if ((dot_state > 1) &&
7987                            ((dirent->name_len & 0xFF) == 2) &&
7988                            (dirent->name[0] == '.') &&
7989                            (dirent->name[1] == '.')) {
7990                         /*
7991                          * If there's a '..' entry in anything other
7992                          * than the second directory entry, it's a
7993                          * duplicate entry that should be removed.
7994                          */
7995                         problem = PR_2_DUP_DOT_DOT;
7996                 } else if ((dot_state > 1) &&
7997                            (dirent->inode == EXT2_ROOT_INO)) {
7998                         /*
7999                          * Don't allow links to the root directory.
8000                          * We check this specially to make sure we
8001                          * catch this error case even if the root
8002                          * directory hasn't been created yet.
8003                          */
8004                         problem = PR_2_LINK_ROOT;
8005                 } else if ((dot_state > 1) &&
8006                            (dirent->name_len & 0xFF) == 0) {
8007                         /*
8008                          * Don't allow zero-length directory names.
8009                          */
8010                         problem = PR_2_NULL_NAME;
8011                 }
8012
8013                 if (problem) {
8014                         if (fix_problem(ctx, problem, &cd->pctx)) {
8015                                 dirent->inode = 0;
8016                                 dir_modified++;
8017                                 goto next;
8018                         } else {
8019                                 ext2fs_unmark_valid(fs);
8020                                 if (problem == PR_2_BAD_INO)
8021                                         goto next;
8022                         }
8023                 }
8024
8025                 /*
8026                  * If the inode was marked as having bad fields in
8027                  * pass1, process it and offer to fix/clear it.
8028                  * (We wait until now so that we can display the
8029                  * pathname to the user.)
8030                  */
8031                 if (ctx->inode_bad_map &&
8032                     ext2fs_test_inode_bitmap(ctx->inode_bad_map,
8033                                              dirent->inode)) {
8034                         if (e2fsck_process_bad_inode(ctx, ino,
8035                                                      dirent->inode,
8036                                                      buf + fs->blocksize)) {
8037                                 dirent->inode = 0;
8038                                 dir_modified++;
8039                                 goto next;
8040                         }
8041                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8042                                 return DIRENT_ABORT;
8043                 }
8044
8045                 if (check_name(ctx, dirent, &cd->pctx))
8046                         dir_modified++;
8047
8048                 if (check_filetype(ctx, dirent, &cd->pctx))
8049                         dir_modified++;
8050
8051 #ifdef ENABLE_HTREE
8052                 if (dx_db) {
8053                         ext2fs_dirhash(dx_dir->hashversion, dirent->name,
8054                                        (dirent->name_len & 0xFF),
8055                                        fs->super->s_hash_seed, &hash, 0);
8056                         if (hash < dx_db->min_hash)
8057                                 dx_db->min_hash = hash;
8058                         if (hash > dx_db->max_hash)
8059                                 dx_db->max_hash = hash;
8060                 }
8061 #endif
8062
8063                 /*
8064                  * If this is a directory, then mark its parent in its
8065                  * dir_info structure.  If the parent field is already
8066                  * filled in, then this directory has more than one
8067                  * hard link.  We assume the first link is correct,
8068                  * and ask the user if he/she wants to clear this one.
8069                  */
8070                 if ((dot_state > 1) &&
8071                     (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
8072                                               dirent->inode))) {
8073                         subdir = e2fsck_get_dir_info(ctx, dirent->inode);
8074                         if (!subdir) {
8075                                 cd->pctx.ino = dirent->inode;
8076                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
8077                                 goto abort_free_dict;
8078                         }
8079                         if (subdir->parent) {
8080                                 cd->pctx.ino2 = subdir->parent;
8081                                 if (fix_problem(ctx, PR_2_LINK_DIR,
8082                                                 &cd->pctx)) {
8083                                         dirent->inode = 0;
8084                                         dir_modified++;
8085                                         goto next;
8086                                 }
8087                                 cd->pctx.ino2 = 0;
8088                         } else
8089                                 subdir->parent = ino;
8090                 }
8091
8092                 if (dups_found) {
8093                         ;
8094                 } else if (dict_lookup(&de_dict, dirent)) {
8095                         clear_problem_context(&pctx);
8096                         pctx.ino = ino;
8097                         pctx.dirent = dirent;
8098                         fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
8099                         if (!ctx->dirs_to_hash)
8100                                 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
8101                         if (ctx->dirs_to_hash)
8102                                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
8103                         dups_found++;
8104                 } else
8105                         dict_alloc_insert(&de_dict, dirent, dirent);
8106
8107                 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
8108                                         &links);
8109                 if (links > 1)
8110                         ctx->fs_links_count++;
8111                 ctx->fs_total_count++;
8112         next:
8113                 prev = dirent;
8114                 offset += dirent->rec_len;
8115                 dot_state++;
8116         } while (offset < fs->blocksize);
8117 #if 0
8118         printf("\n");
8119 #endif
8120 #ifdef ENABLE_HTREE
8121         if (dx_db) {
8122 #ifdef DX_DEBUG
8123                 printf("db_block %d, type %d, min_hash 0x%0x, max_hash 0x%0x\n",
8124                        db->blockcnt, dx_db->type,
8125                        dx_db->min_hash, dx_db->max_hash);
8126 #endif
8127                 cd->pctx.dir = cd->pctx.ino;
8128                 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
8129                     (dx_db->type == DX_DIRBLOCK_NODE))
8130                         parse_int_node(fs, db, cd, dx_dir, buf);
8131         }
8132 #endif /* ENABLE_HTREE */
8133         if (offset != fs->blocksize) {
8134                 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
8135                 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
8136                         dirent->rec_len = cd->pctx.num;
8137                         dir_modified++;
8138                 }
8139         }
8140         if (dir_modified) {
8141                 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
8142                 if (cd->pctx.errcode) {
8143                         if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
8144                                          &cd->pctx))
8145                                 goto abort_free_dict;
8146                 }
8147                 ext2fs_mark_changed(fs);
8148         }
8149         dict_free_nodes(&de_dict);
8150         return 0;
8151 abort_free_dict:
8152         dict_free_nodes(&de_dict);
8153         ctx->flags |= E2F_FLAG_ABORT;
8154         return DIRENT_ABORT;
8155 }
8156
8157 /*
8158  * This function is called to deallocate a block, and is an interator
8159  * functioned called by deallocate inode via ext2fs_iterate_block().
8160  */
8161 static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
8162                                   e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
8163                                   blk_t ref_block FSCK_ATTR((unused)),
8164                                   int ref_offset FSCK_ATTR((unused)),
8165                                   void *priv_data)
8166 {
8167         e2fsck_t        ctx = (e2fsck_t) priv_data;
8168
8169         if (HOLE_BLKADDR(*block_nr))
8170                 return 0;
8171         if ((*block_nr < fs->super->s_first_data_block) ||
8172             (*block_nr >= fs->super->s_blocks_count))
8173                 return 0;
8174         ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
8175         ext2fs_block_alloc_stats(fs, *block_nr, -1);
8176         return 0;
8177 }
8178
8179 /*
8180  * This fuction deallocates an inode
8181  */
8182 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
8183 {
8184         ext2_filsys fs = ctx->fs;
8185         struct ext2_inode       inode;
8186         struct problem_context  pctx;
8187         __u32                   count;
8188
8189         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
8190         e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
8191         inode.i_links_count = 0;
8192         inode.i_dtime = time(0);
8193         e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
8194         clear_problem_context(&pctx);
8195         pctx.ino = ino;
8196
8197         /*
8198          * Fix up the bitmaps...
8199          */
8200         e2fsck_read_bitmaps(ctx);
8201         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
8202         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
8203         if (ctx->inode_bad_map)
8204                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
8205         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
8206
8207         if (inode.i_file_acl &&
8208             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
8209                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
8210                                                    block_buf, -1, &count);
8211                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
8212                         pctx.errcode = 0;
8213                         count = 1;
8214                 }
8215                 if (pctx.errcode) {
8216                         pctx.blk = inode.i_file_acl;
8217                         fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
8218                         ctx->flags |= E2F_FLAG_ABORT;
8219                         return;
8220                 }
8221                 if (count == 0) {
8222                         ext2fs_unmark_block_bitmap(ctx->block_found_map,
8223                                                    inode.i_file_acl);
8224                         ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
8225                 }
8226                 inode.i_file_acl = 0;
8227         }
8228
8229         if (!ext2fs_inode_has_valid_blocks(&inode))
8230                 return;
8231
8232         if (LINUX_S_ISREG(inode.i_mode) &&
8233             (inode.i_size_high || inode.i_size & 0x80000000UL))
8234                 ctx->large_files--;
8235
8236         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
8237                                             deallocate_inode_block, ctx);
8238         if (pctx.errcode) {
8239                 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
8240                 ctx->flags |= E2F_FLAG_ABORT;
8241                 return;
8242         }
8243 }
8244
8245 /*
8246  * This fuction clears the htree flag on an inode
8247  */
8248 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
8249 {
8250         struct ext2_inode       inode;
8251
8252         e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
8253         inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
8254         e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
8255         if (ctx->dirs_to_hash)
8256                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
8257 }
8258
8259
8260 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
8261                                     ext2_ino_t ino, char *buf)
8262 {
8263         ext2_filsys fs = ctx->fs;
8264         struct ext2_inode       inode;
8265         int                     inode_modified = 0;
8266         int                     not_fixed = 0;
8267         unsigned char           *frag, *fsize;
8268         struct problem_context  pctx;
8269         int     problem = 0;
8270
8271         e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
8272
8273         clear_problem_context(&pctx);
8274         pctx.ino = ino;
8275         pctx.dir = dir;
8276         pctx.inode = &inode;
8277
8278         if (inode.i_file_acl &&
8279             !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
8280             fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
8281                 inode.i_file_acl = 0;
8282 #ifdef EXT2FS_ENABLE_SWAPFS
8283                 /*
8284                  * This is a special kludge to deal with long symlinks
8285                  * on big endian systems.  i_blocks had already been
8286                  * decremented earlier in pass 1, but since i_file_acl
8287                  * hadn't yet been cleared, ext2fs_read_inode()
8288                  * assumed that the file was short symlink and would
8289                  * not have byte swapped i_block[0].  Hence, we have
8290                  * to byte-swap it here.
8291                  */
8292                 if (LINUX_S_ISLNK(inode.i_mode) &&
8293                     (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
8294                     (inode.i_blocks == fs->blocksize >> 9))
8295                         inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
8296 #endif
8297                 inode_modified++;
8298         } else
8299                 not_fixed++;
8300
8301         if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
8302             !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
8303             !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
8304             !(LINUX_S_ISSOCK(inode.i_mode)))
8305                 problem = PR_2_BAD_MODE;
8306         else if (LINUX_S_ISCHR(inode.i_mode)
8307                  && !e2fsck_pass1_check_device_inode(fs, &inode))
8308                 problem = PR_2_BAD_CHAR_DEV;
8309         else if (LINUX_S_ISBLK(inode.i_mode)
8310                  && !e2fsck_pass1_check_device_inode(fs, &inode))
8311                 problem = PR_2_BAD_BLOCK_DEV;
8312         else if (LINUX_S_ISFIFO(inode.i_mode)
8313                  && !e2fsck_pass1_check_device_inode(fs, &inode))
8314                 problem = PR_2_BAD_FIFO;
8315         else if (LINUX_S_ISSOCK(inode.i_mode)
8316                  && !e2fsck_pass1_check_device_inode(fs, &inode))
8317                 problem = PR_2_BAD_SOCKET;
8318         else if (LINUX_S_ISLNK(inode.i_mode)
8319                  && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
8320                 problem = PR_2_INVALID_SYMLINK;
8321         }
8322
8323         if (problem) {
8324                 if (fix_problem(ctx, problem, &pctx)) {
8325                         deallocate_inode(ctx, ino, 0);
8326                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8327                                 return 0;
8328                         return 1;
8329                 } else
8330                         not_fixed++;
8331                 problem = 0;
8332         }
8333
8334         if (inode.i_faddr) {
8335                 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
8336                         inode.i_faddr = 0;
8337                         inode_modified++;
8338                 } else
8339                         not_fixed++;
8340         }
8341
8342         switch (fs->super->s_creator_os) {
8343             case EXT2_OS_LINUX:
8344                 frag = &inode.osd2.linux2.l_i_frag;
8345                 fsize = &inode.osd2.linux2.l_i_fsize;
8346                 break;
8347             case EXT2_OS_HURD:
8348                 frag = &inode.osd2.hurd2.h_i_frag;
8349                 fsize = &inode.osd2.hurd2.h_i_fsize;
8350                 break;
8351             case EXT2_OS_MASIX:
8352                 frag = &inode.osd2.masix2.m_i_frag;
8353                 fsize = &inode.osd2.masix2.m_i_fsize;
8354                 break;
8355             default:
8356                 frag = fsize = 0;
8357         }
8358         if (frag && *frag) {
8359                 pctx.num = *frag;
8360                 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
8361                         *frag = 0;
8362                         inode_modified++;
8363                 } else
8364                         not_fixed++;
8365                 pctx.num = 0;
8366         }
8367         if (fsize && *fsize) {
8368                 pctx.num = *fsize;
8369                 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
8370                         *fsize = 0;
8371                         inode_modified++;
8372                 } else
8373                         not_fixed++;
8374                 pctx.num = 0;
8375         }
8376
8377         if (inode.i_file_acl &&
8378             ((inode.i_file_acl < fs->super->s_first_data_block) ||
8379              (inode.i_file_acl >= fs->super->s_blocks_count))) {
8380                 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
8381                         inode.i_file_acl = 0;
8382                         inode_modified++;
8383                 } else
8384                         not_fixed++;
8385         }
8386         if (inode.i_dir_acl &&
8387             LINUX_S_ISDIR(inode.i_mode)) {
8388                 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
8389                         inode.i_dir_acl = 0;
8390                         inode_modified++;
8391                 } else
8392                         not_fixed++;
8393         }
8394
8395         if (inode_modified)
8396                 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
8397         if (!not_fixed)
8398                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
8399         return 0;
8400 }
8401
8402
8403 /*
8404  * allocate_dir_block --- this function allocates a new directory
8405  *      block for a particular inode; this is done if a directory has
8406  *      a "hole" in it, or if a directory has a illegal block number
8407  *      that was zeroed out and now needs to be replaced.
8408  */
8409 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
8410                               struct problem_context *pctx)
8411 {
8412         ext2_filsys fs = ctx->fs;
8413         blk_t                   blk;
8414         char                    *block;
8415         struct ext2_inode       inode;
8416
8417         if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
8418                 return 1;
8419
8420         /*
8421          * Read the inode and block bitmaps in; we'll be messing with
8422          * them.
8423          */
8424         e2fsck_read_bitmaps(ctx);
8425
8426         /*
8427          * First, find a free block
8428          */
8429         pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8430         if (pctx->errcode) {
8431                 pctx->str = "ext2fs_new_block";
8432                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8433                 return 1;
8434         }
8435         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8436         ext2fs_mark_block_bitmap(fs->block_map, blk);
8437         ext2fs_mark_bb_dirty(fs);
8438
8439         /*
8440          * Now let's create the actual data block for the inode
8441          */
8442         if (db->blockcnt)
8443                 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
8444         else
8445                 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
8446                                                      EXT2_ROOT_INO, &block);
8447
8448         if (pctx->errcode) {
8449                 pctx->str = "ext2fs_new_dir_block";
8450                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8451                 return 1;
8452         }
8453
8454         pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
8455         ext2fs_free_mem(&block);
8456         if (pctx->errcode) {
8457                 pctx->str = "ext2fs_write_dir_block";
8458                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8459                 return 1;
8460         }
8461
8462         /*
8463          * Update the inode block count
8464          */
8465         e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
8466         inode.i_blocks += fs->blocksize / 512;
8467         if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
8468                 inode.i_size = (db->blockcnt+1) * fs->blocksize;
8469         e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
8470
8471         /*
8472          * Finally, update the block pointers for the inode
8473          */
8474         db->blk = blk;
8475         pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
8476                                       0, update_dir_block, db);
8477         if (pctx->errcode) {
8478                 pctx->str = "ext2fs_block_iterate";
8479                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8480                 return 1;
8481         }
8482
8483         return 0;
8484 }
8485
8486 /*
8487  * This is a helper function for allocate_dir_block().
8488  */
8489 static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
8490                             blk_t       *block_nr,
8491                             e2_blkcnt_t blockcnt,
8492                             blk_t ref_block FSCK_ATTR((unused)),
8493                             int ref_offset FSCK_ATTR((unused)),
8494                             void *priv_data)
8495 {
8496         struct ext2_db_entry *db;
8497
8498         db = (struct ext2_db_entry *) priv_data;
8499         if (db->blockcnt == (int) blockcnt) {
8500                 *block_nr = db->blk;
8501                 return BLOCK_CHANGED;
8502         }
8503         return 0;
8504 }
8505
8506 /*
8507  * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
8508  *
8509  * Pass #3 assures that all directories are connected to the
8510  * filesystem tree, using the following algorithm:
8511  *
8512  * First, the root directory is checked to make sure it exists; if
8513  * not, e2fsck will offer to create a new one.  It is then marked as
8514  * "done".
8515  *
8516  * Then, pass3 interates over all directory inodes; for each directory
8517  * it attempts to trace up the filesystem tree, using dirinfo.parent
8518  * until it reaches a directory which has been marked "done".  If it
8519  * can not do so, then the directory must be disconnected, and e2fsck
8520  * will offer to reconnect it to /lost+found.  While it is chasing
8521  * parent pointers up the filesystem tree, if pass3 sees a directory
8522  * twice, then it has detected a filesystem loop, and it will again
8523  * offer to reconnect the directory to /lost+found in to break the
8524  * filesystem loop.
8525  *
8526  * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
8527  * reconnect inodes to /lost+found; this subroutine is also used by
8528  * pass 4.  e2fsck_reconnect_file() calls get_lost_and_found(), which
8529  * is responsible for creating /lost+found if it does not exist.
8530  *
8531  * Pass 3 frees the following data structures:
8532  *      - The dirinfo directory information cache.
8533  */
8534
8535 static void check_root(e2fsck_t ctx);
8536 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
8537                            struct problem_context *pctx);
8538 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
8539
8540 static ext2fs_inode_bitmap inode_loop_detect;
8541 static ext2fs_inode_bitmap inode_done_map;
8542
8543 static void e2fsck_pass3(e2fsck_t ctx)
8544 {
8545         ext2_filsys fs = ctx->fs;
8546         int             i;
8547 #ifdef RESOURCE_TRACK
8548         struct resource_track   rtrack;
8549 #endif
8550         struct problem_context  pctx;
8551         struct dir_info *dir;
8552         unsigned long maxdirs, count;
8553
8554 #ifdef RESOURCE_TRACK
8555         init_resource_track(&rtrack);
8556 #endif
8557
8558         clear_problem_context(&pctx);
8559
8560 #ifdef MTRACE
8561         mtrace_print("Pass 3");
8562 #endif
8563
8564         if (!(ctx->options & E2F_OPT_PREEN))
8565                 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
8566
8567         /*
8568          * Allocate some bitmaps to do loop detection.
8569          */
8570         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
8571                                                     &inode_done_map);
8572         if (pctx.errcode) {
8573                 pctx.num = 2;
8574                 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
8575                 ctx->flags |= E2F_FLAG_ABORT;
8576                 goto abort_exit;
8577         }
8578 #ifdef RESOURCE_TRACK
8579         if (ctx->options & E2F_OPT_TIME) {
8580                 e2fsck_clear_progbar(ctx);
8581                 print_resource_track(_("Peak memory"), &ctx->global_rtrack);
8582         }
8583 #endif
8584
8585         check_root(ctx);
8586         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8587                 goto abort_exit;
8588
8589         ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
8590
8591         maxdirs = e2fsck_get_num_dirinfo(ctx);
8592         count = 1;
8593
8594         if (ctx->progress)
8595                 if ((ctx->progress)(ctx, 3, 0, maxdirs))
8596                         goto abort_exit;
8597
8598         for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
8599                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8600                         goto abort_exit;
8601                 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
8602                         goto abort_exit;
8603                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
8604                         if (check_directory(ctx, dir, &pctx))
8605                                 goto abort_exit;
8606         }
8607
8608         /*
8609          * Force the creation of /lost+found if not present
8610          */
8611         if ((ctx->flags & E2F_OPT_READONLY) == 0)
8612                 e2fsck_get_lost_and_found(ctx, 1);
8613
8614         /*
8615          * If there are any directories that need to be indexed or
8616          * optimized, do it here.
8617          */
8618         e2fsck_rehash_directories(ctx);
8619
8620 abort_exit:
8621         e2fsck_free_dir_info(ctx);
8622         ext2fs_free_inode_bitmap(inode_loop_detect);
8623         inode_loop_detect = 0;
8624         ext2fs_free_inode_bitmap(inode_done_map);
8625         inode_done_map = 0;
8626
8627 #ifdef RESOURCE_TRACK
8628         if (ctx->options & E2F_OPT_TIME2) {
8629                 e2fsck_clear_progbar(ctx);
8630                 print_resource_track(_("Pass 3"), &rtrack);
8631         }
8632 #endif
8633 }
8634
8635 /*
8636  * This makes sure the root inode is present; if not, we ask if the
8637  * user wants us to create it.  Not creating it is a fatal error.
8638  */
8639 static void check_root(e2fsck_t ctx)
8640 {
8641         ext2_filsys fs = ctx->fs;
8642         blk_t                   blk;
8643         struct ext2_inode       inode;
8644         char *                  block;
8645         struct problem_context  pctx;
8646
8647         clear_problem_context(&pctx);
8648
8649         if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
8650                 /*
8651                  * If the root inode is not a directory, die here.  The
8652                  * user must have answered 'no' in pass1 when we
8653                  * offered to clear it.
8654                  */
8655                 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
8656                                                EXT2_ROOT_INO))) {
8657                         fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
8658                         ctx->flags |= E2F_FLAG_ABORT;
8659                 }
8660                 return;
8661         }
8662
8663         if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
8664                 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
8665                 ctx->flags |= E2F_FLAG_ABORT;
8666                 return;
8667         }
8668
8669         e2fsck_read_bitmaps(ctx);
8670
8671         /*
8672          * First, find a free block
8673          */
8674         pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8675         if (pctx.errcode) {
8676                 pctx.str = "ext2fs_new_block";
8677                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8678                 ctx->flags |= E2F_FLAG_ABORT;
8679                 return;
8680         }
8681         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8682         ext2fs_mark_block_bitmap(fs->block_map, blk);
8683         ext2fs_mark_bb_dirty(fs);
8684
8685         /*
8686          * Now let's create the actual data block for the inode
8687          */
8688         pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
8689                                             &block);
8690         if (pctx.errcode) {
8691                 pctx.str = "ext2fs_new_dir_block";
8692                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8693                 ctx->flags |= E2F_FLAG_ABORT;
8694                 return;
8695         }
8696
8697         pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
8698         if (pctx.errcode) {
8699                 pctx.str = "ext2fs_write_dir_block";
8700                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8701                 ctx->flags |= E2F_FLAG_ABORT;
8702                 return;
8703         }
8704         ext2fs_free_mem(&block);
8705
8706         /*
8707          * Set up the inode structure
8708          */
8709         memset(&inode, 0, sizeof(inode));
8710         inode.i_mode = 040755;
8711         inode.i_size = fs->blocksize;
8712         inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
8713         inode.i_links_count = 2;
8714         inode.i_blocks = fs->blocksize / 512;
8715         inode.i_block[0] = blk;
8716
8717         /*
8718          * Write out the inode.
8719          */
8720         pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
8721         if (pctx.errcode) {
8722                 pctx.str = "ext2fs_write_inode";
8723                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8724                 ctx->flags |= E2F_FLAG_ABORT;
8725                 return;
8726         }
8727
8728         /*
8729          * Miscellaneous bookkeeping...
8730          */
8731         e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
8732         ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
8733         ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
8734
8735         ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
8736         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
8737         ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
8738         ext2fs_mark_ib_dirty(fs);
8739 }
8740
8741 /*
8742  * This subroutine is responsible for making sure that a particular
8743  * directory is connected to the root; if it isn't we trace it up as
8744  * far as we can go, and then offer to connect the resulting parent to
8745  * the lost+found.  We have to do loop detection; if we ever discover
8746  * a loop, we treat that as a disconnected directory and offer to
8747  * reparent it to lost+found.
8748  *
8749  * However, loop detection is expensive, because for very large
8750  * filesystems, the inode_loop_detect bitmap is huge, and clearing it
8751  * is non-trivial.  Loops in filesystems are also a rare error case,
8752  * and we shouldn't optimize for error cases.  So we try two passes of
8753  * the algorithm.  The first time, we ignore loop detection and merely
8754  * increment a counter; if the counter exceeds some extreme threshold,
8755  * then we try again with the loop detection bitmap enabled.
8756  */
8757 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
8758                            struct problem_context *pctx)
8759 {
8760         ext2_filsys     fs = ctx->fs;
8761         struct dir_info *p = dir;
8762         int             loop_pass = 0, parent_count = 0;
8763
8764         if (!p)
8765                 return 0;
8766
8767         while (1) {
8768                 /*
8769                  * Mark this inode as being "done"; by the time we
8770                  * return from this function, the inode we either be
8771                  * verified as being connected to the directory tree,
8772                  * or we will have offered to reconnect this to
8773                  * lost+found.
8774                  *
8775                  * If it was marked done already, then we've reached a
8776                  * parent we've already checked.
8777                  */
8778                 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
8779                         break;
8780
8781                 /*
8782                  * If this directory doesn't have a parent, or we've
8783                  * seen the parent once already, then offer to
8784                  * reparent it to lost+found
8785                  */
8786                 if (!p->parent ||
8787                     (loop_pass &&
8788                      (ext2fs_test_inode_bitmap(inode_loop_detect,
8789                                               p->parent)))) {
8790                         pctx->ino = p->ino;
8791                         if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
8792                                 if (e2fsck_reconnect_file(ctx, pctx->ino))
8793                                         ext2fs_unmark_valid(fs);
8794                                 else {
8795                                         p = e2fsck_get_dir_info(ctx, pctx->ino);
8796                                         p->parent = ctx->lost_and_found;
8797                                         fix_dotdot(ctx, p, ctx->lost_and_found);
8798                                 }
8799                         }
8800                         break;
8801                 }
8802                 p = e2fsck_get_dir_info(ctx, p->parent);
8803                 if (!p) {
8804                         fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
8805                         return 0;
8806                 }
8807                 if (loop_pass) {
8808                         ext2fs_mark_inode_bitmap(inode_loop_detect,
8809                                                  p->ino);
8810                 } else if (parent_count++ > 2048) {
8811                         /*
8812                          * If we've run into a path depth that's
8813                          * greater than 2048, try again with the inode
8814                          * loop bitmap turned on and start from the
8815                          * top.
8816                          */
8817                         loop_pass = 1;
8818                         if (inode_loop_detect)
8819                                 ext2fs_clear_inode_bitmap(inode_loop_detect);
8820                         else {
8821                                 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
8822                                 if (pctx->errcode) {
8823                                         pctx->num = 1;
8824                                         fix_problem(ctx,
8825                                     PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
8826                                         ctx->flags |= E2F_FLAG_ABORT;
8827                                         return -1;
8828                                 }
8829                         }
8830                         p = dir;
8831                 }
8832         }
8833
8834         /*
8835          * Make sure that .. and the parent directory are the same;
8836          * offer to fix it if not.
8837          */
8838         if (dir->parent != dir->dotdot) {
8839                 pctx->ino = dir->ino;
8840                 pctx->ino2 = dir->dotdot;
8841                 pctx->dir = dir->parent;
8842                 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
8843                         fix_dotdot(ctx, dir, dir->parent);
8844         }
8845         return 0;
8846 }
8847
8848 /*
8849  * This routine gets the lost_and_found inode, making it a directory
8850  * if necessary
8851  */
8852 ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
8853 {
8854         ext2_filsys fs = ctx->fs;
8855         ext2_ino_t                      ino;
8856         blk_t                   blk;
8857         errcode_t               retval;
8858         struct ext2_inode       inode;
8859         char *                  block;
8860         static const char       name[] = "lost+found";
8861         struct  problem_context pctx;
8862         struct dir_info         *dirinfo;
8863
8864         if (ctx->lost_and_found)
8865                 return ctx->lost_and_found;
8866
8867         clear_problem_context(&pctx);
8868
8869         retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
8870                                sizeof(name)-1, 0, &ino);
8871         if (retval && !fix)
8872                 return 0;
8873         if (!retval) {
8874                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
8875                         ctx->lost_and_found = ino;
8876                         return ino;
8877                 }
8878
8879                 /* Lost+found isn't a directory! */
8880                 if (!fix)
8881                         return 0;
8882                 pctx.ino = ino;
8883                 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
8884                         return 0;
8885
8886                 /* OK, unlink the old /lost+found file. */
8887                 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
8888                 if (pctx.errcode) {
8889                         pctx.str = "ext2fs_unlink";
8890                         fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
8891                         return 0;
8892                 }
8893                 dirinfo = e2fsck_get_dir_info(ctx, ino);
8894                 if (dirinfo)
8895                         dirinfo->parent = 0;
8896                 e2fsck_adjust_inode_count(ctx, ino, -1);
8897         } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
8898                 pctx.errcode = retval;
8899                 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
8900         }
8901         if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
8902                 return 0;
8903
8904         /*
8905          * Read the inode and block bitmaps in; we'll be messing with
8906          * them.
8907          */
8908         e2fsck_read_bitmaps(ctx);
8909
8910         /*
8911          * First, find a free block
8912          */
8913         retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8914         if (retval) {
8915                 pctx.errcode = retval;
8916                 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
8917                 return 0;
8918         }
8919         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8920         ext2fs_block_alloc_stats(fs, blk, +1);
8921
8922         /*
8923          * Next find a free inode.
8924          */
8925         retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
8926                                   ctx->inode_used_map, &ino);
8927         if (retval) {
8928                 pctx.errcode = retval;
8929                 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
8930                 return 0;
8931         }
8932         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
8933         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
8934         ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
8935
8936         /*
8937          * Now let's create the actual data block for the inode
8938          */
8939         retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
8940         if (retval) {
8941                 pctx.errcode = retval;
8942                 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
8943                 return 0;
8944         }
8945
8946         retval = ext2fs_write_dir_block(fs, blk, block);
8947         ext2fs_free_mem(&block);
8948         if (retval) {
8949                 pctx.errcode = retval;
8950                 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
8951                 return 0;
8952         }
8953
8954         /*
8955          * Set up the inode structure
8956          */
8957         memset(&inode, 0, sizeof(inode));
8958         inode.i_mode = 040700;
8959         inode.i_size = fs->blocksize;
8960         inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
8961         inode.i_links_count = 2;
8962         inode.i_blocks = fs->blocksize / 512;
8963         inode.i_block[0] = blk;
8964
8965         /*
8966          * Next, write out the inode.
8967          */
8968         pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
8969         if (pctx.errcode) {
8970                 pctx.str = "ext2fs_write_inode";
8971                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
8972                 return 0;
8973         }
8974         /*
8975          * Finally, create the directory link
8976          */
8977         pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
8978         if (pctx.errcode) {
8979                 pctx.str = "ext2fs_link";
8980                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
8981                 return 0;
8982         }
8983
8984         /*
8985          * Miscellaneous bookkeeping that needs to be kept straight.
8986          */
8987         e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
8988         e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
8989         ext2fs_icount_store(ctx->inode_count, ino, 2);
8990         ext2fs_icount_store(ctx->inode_link_info, ino, 2);
8991         ctx->lost_and_found = ino;
8992 #if 0
8993         printf("/lost+found created; inode #%lu\n", ino);
8994 #endif
8995         return ino;
8996 }
8997
8998 /*
8999  * This routine will connect a file to lost+found
9000  */
9001 int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
9002 {
9003         ext2_filsys fs = ctx->fs;
9004         errcode_t       retval;
9005         char            name[80];
9006         struct problem_context  pctx;
9007         struct ext2_inode       inode;
9008         int             file_type = 0;
9009
9010         clear_problem_context(&pctx);
9011         pctx.ino = ino;
9012
9013         if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
9014                 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
9015                         ctx->bad_lost_and_found++;
9016         }
9017         if (ctx->bad_lost_and_found) {
9018                 fix_problem(ctx, PR_3_NO_LPF, &pctx);
9019                 return 1;
9020         }
9021
9022         sprintf(name, "#%u", ino);
9023         if (ext2fs_read_inode(fs, ino, &inode) == 0)
9024                 file_type = ext2_file_type(inode.i_mode);
9025         retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
9026         if (retval == EXT2_ET_DIR_NO_SPACE) {
9027                 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
9028                         return 1;
9029                 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
9030                                                  1, 0);
9031                 if (retval) {
9032                         pctx.errcode = retval;
9033                         fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
9034                         return 1;
9035                 }
9036                 retval = ext2fs_link(fs, ctx->lost_and_found, name,
9037                                      ino, file_type);
9038         }
9039         if (retval) {
9040                 pctx.errcode = retval;
9041                 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
9042                 return 1;
9043         }
9044         e2fsck_adjust_inode_count(ctx, ino, 1);
9045
9046         return 0;
9047 }
9048
9049 /*
9050  * Utility routine to adjust the inode counts on an inode.
9051  */
9052 errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
9053 {
9054         ext2_filsys fs = ctx->fs;
9055         errcode_t               retval;
9056         struct ext2_inode       inode;
9057
9058         if (!ino)
9059                 return 0;
9060
9061         retval = ext2fs_read_inode(fs, ino, &inode);
9062         if (retval)
9063                 return retval;
9064
9065 #if 0
9066         printf("Adjusting link count for inode %lu by %d (from %d)\n", ino, adj,
9067                inode.i_links_count);
9068 #endif
9069
9070         if (adj == 1) {
9071                 ext2fs_icount_increment(ctx->inode_count, ino, 0);
9072                 if (inode.i_links_count == (__u16) ~0)
9073                         return 0;
9074                 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
9075                 inode.i_links_count++;
9076         } else if (adj == -1) {
9077                 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
9078                 if (inode.i_links_count == 0)
9079                         return 0;
9080                 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
9081                 inode.i_links_count--;
9082         }
9083
9084         retval = ext2fs_write_inode(fs, ino, &inode);
9085         if (retval)
9086                 return retval;
9087
9088         return 0;
9089 }
9090
9091 /*
9092  * Fix parent --- this routine fixes up the parent of a directory.
9093  */
9094 struct fix_dotdot_struct {
9095         ext2_filsys     fs;
9096         ext2_ino_t      parent;
9097         int             done;
9098         e2fsck_t        ctx;
9099 };
9100
9101 static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
9102                            int  offset FSCK_ATTR((unused)),
9103                            int  blocksize FSCK_ATTR((unused)),
9104                            char *buf FSCK_ATTR((unused)),
9105                            void *priv_data)
9106 {
9107         struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
9108         errcode_t       retval;
9109         struct problem_context pctx;
9110
9111         if ((dirent->name_len & 0xFF) != 2)
9112                 return 0;
9113         if (strncmp(dirent->name, "..", 2))
9114                 return 0;
9115
9116         clear_problem_context(&pctx);
9117
9118         retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
9119         if (retval) {
9120                 pctx.errcode = retval;
9121                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
9122         }
9123         retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
9124         if (retval) {
9125                 pctx.errcode = retval;
9126                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
9127         }
9128         dirent->inode = fp->parent;
9129
9130         fp->done++;
9131         return DIRENT_ABORT | DIRENT_CHANGED;
9132 }
9133
9134 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
9135 {
9136         ext2_filsys fs = ctx->fs;
9137         errcode_t       retval;
9138         struct fix_dotdot_struct fp;
9139         struct problem_context pctx;
9140
9141         fp.fs = fs;
9142         fp.parent = parent;
9143         fp.done = 0;
9144         fp.ctx = ctx;
9145
9146 #if 0
9147         printf("Fixing '..' of inode %lu to be %lu...\n", dir->ino, parent);
9148 #endif
9149
9150         retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
9151                                     0, fix_dotdot_proc, &fp);
9152         if (retval || !fp.done) {
9153                 clear_problem_context(&pctx);
9154                 pctx.ino = dir->ino;
9155                 pctx.errcode = retval;
9156                 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
9157                             PR_3_FIX_PARENT_NOFIND, &pctx);
9158                 ext2fs_unmark_valid(fs);
9159         }
9160         dir->dotdot = parent;
9161
9162         return;
9163 }
9164
9165 /*
9166  * These routines are responsible for expanding a /lost+found if it is
9167  * too small.
9168  */
9169
9170 struct expand_dir_struct {
9171         int                     num;
9172         int                     guaranteed_size;
9173         int                     newblocks;
9174         int                     last_block;
9175         errcode_t               err;
9176         e2fsck_t                ctx;
9177 };
9178
9179 static int expand_dir_proc(ext2_filsys fs,
9180                            blk_t        *blocknr,
9181                            e2_blkcnt_t  blockcnt,
9182                            blk_t ref_block FSCK_ATTR((unused)),
9183                            int ref_offset FSCK_ATTR((unused)),
9184                            void *priv_data)
9185 {
9186         struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
9187         blk_t   new_blk;
9188         static blk_t    last_blk = 0;
9189         char            *block;
9190         errcode_t       retval;
9191         e2fsck_t        ctx;
9192
9193         ctx = es->ctx;
9194
9195         if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
9196                 return BLOCK_ABORT;
9197
9198         if (blockcnt > 0)
9199                 es->last_block = blockcnt;
9200         if (*blocknr) {
9201                 last_blk = *blocknr;
9202                 return 0;
9203         }
9204         retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
9205                                   &new_blk);
9206         if (retval) {
9207                 es->err = retval;
9208                 return BLOCK_ABORT;
9209         }
9210         if (blockcnt > 0) {
9211                 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
9212                 if (retval) {
9213                         es->err = retval;
9214                         return BLOCK_ABORT;
9215                 }
9216                 es->num--;
9217                 retval = ext2fs_write_dir_block(fs, new_blk, block);
9218         } else {
9219                 retval = ext2fs_get_mem(fs->blocksize, &block);
9220                 if (retval) {
9221                         es->err = retval;
9222                         return BLOCK_ABORT;
9223                 }
9224                 memset(block, 0, fs->blocksize);
9225                 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
9226         }
9227         if (retval) {
9228                 es->err = retval;
9229                 return BLOCK_ABORT;
9230         }
9231         ext2fs_free_mem(&block);
9232         *blocknr = new_blk;
9233         ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
9234         ext2fs_block_alloc_stats(fs, new_blk, +1);
9235         es->newblocks++;
9236
9237         if (es->num == 0)
9238                 return (BLOCK_CHANGED | BLOCK_ABORT);
9239         else
9240                 return BLOCK_CHANGED;
9241 }
9242
9243 errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
9244                                   int num, int guaranteed_size)
9245 {
9246         ext2_filsys fs = ctx->fs;
9247         errcode_t       retval;
9248         struct expand_dir_struct es;
9249         struct ext2_inode       inode;
9250
9251         if (!(fs->flags & EXT2_FLAG_RW))
9252                 return EXT2_ET_RO_FILSYS;
9253
9254         /*
9255          * Read the inode and block bitmaps in; we'll be messing with
9256          * them.
9257          */
9258         e2fsck_read_bitmaps(ctx);
9259
9260         retval = ext2fs_check_directory(fs, dir);
9261         if (retval)
9262                 return retval;
9263
9264         es.num = num;
9265         es.guaranteed_size = guaranteed_size;
9266         es.last_block = 0;
9267         es.err = 0;
9268         es.newblocks = 0;
9269         es.ctx = ctx;
9270
9271         retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
9272                                        0, expand_dir_proc, &es);
9273
9274         if (es.err)
9275                 return es.err;
9276
9277         /*
9278          * Update the size and block count fields in the inode.
9279          */
9280         retval = ext2fs_read_inode(fs, dir, &inode);
9281         if (retval)
9282                 return retval;
9283
9284         inode.i_size = (es.last_block + 1) * fs->blocksize;
9285         inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
9286
9287         e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
9288
9289         return 0;
9290 }
9291
9292 /*
9293  * pass4.c -- pass #4 of e2fsck: Check reference counts
9294  *
9295  * Pass 4 frees the following data structures:
9296  *      - A bitmap of which inodes are in bad blocks.   (inode_bb_map)
9297  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
9298  */
9299
9300 /*
9301  * This routine is called when an inode is not connected to the
9302  * directory tree.
9303  *
9304  * This subroutine returns 1 then the caller shouldn't bother with the
9305  * rest of the pass 4 tests.
9306  */
9307 static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
9308 {
9309         ext2_filsys fs = ctx->fs;
9310         struct ext2_inode       inode;
9311         struct problem_context  pctx;
9312
9313         e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
9314         clear_problem_context(&pctx);
9315         pctx.ino = i;
9316         pctx.inode = &inode;
9317
9318         /*
9319          * Offer to delete any zero-length files that does not have
9320          * blocks.  If there is an EA block, it might have useful
9321          * information, so we won't prompt to delete it, but let it be
9322          * reconnected to lost+found.
9323          */
9324         if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
9325                                 LINUX_S_ISDIR(inode.i_mode))) {
9326                 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
9327                         ext2fs_icount_store(ctx->inode_link_info, i, 0);
9328                         inode.i_links_count = 0;
9329                         inode.i_dtime = time(0);
9330                         e2fsck_write_inode(ctx, i, &inode,
9331                                            "disconnect_inode");
9332                         /*
9333                          * Fix up the bitmaps...
9334                          */
9335                         e2fsck_read_bitmaps(ctx);
9336                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
9337                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
9338                         ext2fs_inode_alloc_stats2(fs, i, -1,
9339                                                   LINUX_S_ISDIR(inode.i_mode));
9340                         return 0;
9341                 }
9342         }
9343
9344         /*
9345          * Prompt to reconnect.
9346          */
9347         if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
9348                 if (e2fsck_reconnect_file(ctx, i))
9349                         ext2fs_unmark_valid(fs);
9350         } else {
9351                 /*
9352                  * If we don't attach the inode, then skip the
9353                  * i_links_test since there's no point in trying to
9354                  * force i_links_count to zero.
9355                  */
9356                 ext2fs_unmark_valid(fs);
9357                 return 1;
9358         }
9359         return 0;
9360 }
9361
9362
9363 static void e2fsck_pass4(e2fsck_t ctx)
9364 {
9365         ext2_filsys fs = ctx->fs;
9366         ext2_ino_t      i;
9367         struct ext2_inode       inode;
9368 #ifdef RESOURCE_TRACK
9369         struct resource_track   rtrack;
9370 #endif
9371         struct problem_context  pctx;
9372         __u16   link_count, link_counted;
9373         char    *buf = 0;
9374         int     group, maxgroup;
9375
9376 #ifdef RESOURCE_TRACK
9377         init_resource_track(&rtrack);
9378 #endif
9379
9380 #ifdef MTRACE
9381         mtrace_print("Pass 4");
9382 #endif
9383
9384         clear_problem_context(&pctx);
9385
9386         if (!(ctx->options & E2F_OPT_PREEN))
9387                 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
9388
9389         group = 0;
9390         maxgroup = fs->group_desc_count;
9391         if (ctx->progress)
9392                 if ((ctx->progress)(ctx, 4, 0, maxgroup))
9393                         return;
9394
9395         for (i=1; i <= fs->super->s_inodes_count; i++) {
9396                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9397                         return;
9398                 if ((i % fs->super->s_inodes_per_group) == 0) {
9399                         group++;
9400                         if (ctx->progress)
9401                                 if ((ctx->progress)(ctx, 4, group, maxgroup))
9402                                         return;
9403                 }
9404                 if (i == EXT2_BAD_INO ||
9405                     (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
9406                         continue;
9407                 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
9408                     (ctx->inode_imagic_map &&
9409                      ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)) ||
9410                     (ctx->inode_bb_map &&
9411                      ext2fs_test_inode_bitmap(ctx->inode_bb_map, i)))
9412                         continue;
9413                 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
9414                 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
9415                 if (link_counted == 0) {
9416                         if (!buf)
9417                                 buf = e2fsck_allocate_memory(ctx,
9418                                      fs->blocksize, "bad_inode buffer");
9419                         if (e2fsck_process_bad_inode(ctx, 0, i, buf))
9420                                 continue;
9421                         if (disconnect_inode(ctx, i))
9422                                 continue;
9423                         ext2fs_icount_fetch(ctx->inode_link_info, i,
9424                                             &link_count);
9425                         ext2fs_icount_fetch(ctx->inode_count, i,
9426                                             &link_counted);
9427                 }
9428                 if (link_counted != link_count) {
9429                         e2fsck_read_inode(ctx, i, &inode, "pass4");
9430                         pctx.ino = i;
9431                         pctx.inode = &inode;
9432                         if (link_count != inode.i_links_count) {
9433                                 pctx.num = link_count;
9434                                 fix_problem(ctx,
9435                                             PR_4_INCONSISTENT_COUNT, &pctx);
9436                         }
9437                         pctx.num = link_counted;
9438                         if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
9439                                 inode.i_links_count = link_counted;
9440                                 e2fsck_write_inode(ctx, i, &inode, "pass4");
9441                         }
9442                 }
9443         }
9444         ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
9445         ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
9446         ext2fs_free_inode_bitmap(ctx->inode_bb_map);
9447         ctx->inode_bb_map = 0;
9448         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
9449         ctx->inode_imagic_map = 0;
9450         ext2fs_free_mem(&buf);
9451 #ifdef RESOURCE_TRACK
9452         if (ctx->options & E2F_OPT_TIME2) {
9453                 e2fsck_clear_progbar(ctx);
9454                 print_resource_track(_("Pass 4"), &rtrack);
9455         }
9456 #endif
9457 }
9458
9459 /*
9460  * pass5.c --- check block and inode bitmaps against on-disk bitmaps
9461  */
9462
9463 #define NO_BLK ((blk_t) -1)
9464
9465 static void print_bitmap_problem(e2fsck_t ctx, int problem,
9466                             struct problem_context *pctx)
9467 {
9468         switch (problem) {
9469         case PR_5_BLOCK_UNUSED:
9470                 if (pctx->blk == pctx->blk2)
9471                         pctx->blk2 = 0;
9472                 else
9473                         problem = PR_5_BLOCK_RANGE_UNUSED;
9474                 break;
9475         case PR_5_BLOCK_USED:
9476                 if (pctx->blk == pctx->blk2)
9477                         pctx->blk2 = 0;
9478                 else
9479                         problem = PR_5_BLOCK_RANGE_USED;
9480                 break;
9481         case PR_5_INODE_UNUSED:
9482                 if (pctx->ino == pctx->ino2)
9483                         pctx->ino2 = 0;
9484                 else
9485                         problem = PR_5_INODE_RANGE_UNUSED;
9486                 break;
9487         case PR_5_INODE_USED:
9488                 if (pctx->ino == pctx->ino2)
9489                         pctx->ino2 = 0;
9490                 else
9491                         problem = PR_5_INODE_RANGE_USED;
9492                 break;
9493         }
9494         fix_problem(ctx, problem, pctx);
9495         pctx->blk = pctx->blk2 = NO_BLK;
9496         pctx->ino = pctx->ino2 = 0;
9497 }
9498
9499 static void check_block_bitmaps(e2fsck_t ctx)
9500 {
9501         ext2_filsys fs = ctx->fs;
9502         blk_t   i;
9503         int     *free_array;
9504         int     group = 0;
9505         unsigned int    blocks = 0;
9506         unsigned int    free_blocks = 0;
9507         int     group_free = 0;
9508         int     actual, bitmap;
9509         struct problem_context  pctx;
9510         int     problem, save_problem, fixit, had_problem;
9511         errcode_t       retval;
9512
9513         clear_problem_context(&pctx);
9514         free_array = (int *) e2fsck_allocate_memory(ctx,
9515             fs->group_desc_count * sizeof(int), "free block count array");
9516
9517         if ((fs->super->s_first_data_block <
9518              ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
9519             (fs->super->s_blocks_count-1 >
9520              ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
9521                 pctx.num = 1;
9522                 pctx.blk = fs->super->s_first_data_block;
9523                 pctx.blk2 = fs->super->s_blocks_count -1;
9524                 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
9525                 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
9526                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9527
9528                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9529                 return;
9530         }
9531
9532         if ((fs->super->s_first_data_block <
9533              ext2fs_get_block_bitmap_start(fs->block_map)) ||
9534             (fs->super->s_blocks_count-1 >
9535              ext2fs_get_block_bitmap_end(fs->block_map))) {
9536                 pctx.num = 2;
9537                 pctx.blk = fs->super->s_first_data_block;
9538                 pctx.blk2 = fs->super->s_blocks_count -1;
9539                 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
9540                 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
9541                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9542
9543                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9544                 return;
9545         }
9546
9547 redo_counts:
9548         had_problem = 0;
9549         save_problem = 0;
9550         pctx.blk = pctx.blk2 = NO_BLK;
9551         for (i = fs->super->s_first_data_block;
9552              i < fs->super->s_blocks_count;
9553              i++) {
9554                 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
9555                 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
9556
9557                 if (actual == bitmap)
9558                         goto do_counts;
9559
9560                 if (!actual && bitmap) {
9561                         /*
9562                          * Block not used, but marked in use in the bitmap.
9563                          */
9564                         problem = PR_5_BLOCK_UNUSED;
9565                 } else {
9566                         /*
9567                          * Block used, but not marked in use in the bitmap.
9568                          */
9569                         problem = PR_5_BLOCK_USED;
9570                 }
9571                 if (pctx.blk == NO_BLK) {
9572                         pctx.blk = pctx.blk2 = i;
9573                         save_problem = problem;
9574                 } else {
9575                         if ((problem == save_problem) &&
9576                             (pctx.blk2 == i-1))
9577                                 pctx.blk2++;
9578                         else {
9579                                 print_bitmap_problem(ctx, save_problem, &pctx);
9580                                 pctx.blk = pctx.blk2 = i;
9581                                 save_problem = problem;
9582                         }
9583                 }
9584                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
9585                 had_problem++;
9586
9587         do_counts:
9588                 if (!bitmap) {
9589                         group_free++;
9590                         free_blocks++;
9591                 }
9592                 blocks ++;
9593                 if ((blocks == fs->super->s_blocks_per_group) ||
9594                     (i == fs->super->s_blocks_count-1)) {
9595                         free_array[group] = group_free;
9596                         group ++;
9597                         blocks = 0;
9598                         group_free = 0;
9599                         if (ctx->progress)
9600                                 if ((ctx->progress)(ctx, 5, group,
9601                                                     fs->group_desc_count*2))
9602                                         return;
9603                 }
9604         }
9605         if (pctx.blk != NO_BLK)
9606                 print_bitmap_problem(ctx, save_problem, &pctx);
9607         if (had_problem)
9608                 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
9609         else
9610                 fixit = -1;
9611         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
9612
9613         if (fixit == 1) {
9614                 ext2fs_free_block_bitmap(fs->block_map);
9615                 retval = ext2fs_copy_bitmap(ctx->block_found_map,
9616                                                   &fs->block_map);
9617                 if (retval) {
9618                         clear_problem_context(&pctx);
9619                         fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
9620                         ctx->flags |= E2F_FLAG_ABORT;
9621                         return;
9622                 }
9623                 ext2fs_set_bitmap_padding(fs->block_map);
9624                 ext2fs_mark_bb_dirty(fs);
9625
9626                 /* Redo the counts */
9627                 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
9628                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
9629                 goto redo_counts;
9630         } else if (fixit == 0)
9631                 ext2fs_unmark_valid(fs);
9632
9633         for (i = 0; i < fs->group_desc_count; i++) {
9634                 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
9635                         pctx.group = i;
9636                         pctx.blk = fs->group_desc[i].bg_free_blocks_count;
9637                         pctx.blk2 = free_array[i];
9638
9639                         if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
9640                                         &pctx)) {
9641                                 fs->group_desc[i].bg_free_blocks_count =
9642                                         free_array[i];
9643                                 ext2fs_mark_super_dirty(fs);
9644                         } else
9645                                 ext2fs_unmark_valid(fs);
9646                 }
9647         }
9648         if (free_blocks != fs->super->s_free_blocks_count) {
9649                 pctx.group = 0;
9650                 pctx.blk = fs->super->s_free_blocks_count;
9651                 pctx.blk2 = free_blocks;
9652
9653                 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
9654                         fs->super->s_free_blocks_count = free_blocks;
9655                         ext2fs_mark_super_dirty(fs);
9656                 } else
9657                         ext2fs_unmark_valid(fs);
9658         }
9659         ext2fs_free_mem(&free_array);
9660 }
9661
9662 static void check_inode_bitmaps(e2fsck_t ctx)
9663 {
9664         ext2_filsys fs = ctx->fs;
9665         ext2_ino_t      i;
9666         unsigned int    free_inodes = 0;
9667         int             group_free = 0;
9668         int             dirs_count = 0;
9669         int             group = 0;
9670         unsigned int    inodes = 0;
9671         int             *free_array;
9672         int             *dir_array;
9673         int             actual, bitmap;
9674         errcode_t       retval;
9675         struct problem_context  pctx;
9676         int             problem, save_problem, fixit, had_problem;
9677
9678         clear_problem_context(&pctx);
9679         free_array = (int *) e2fsck_allocate_memory(ctx,
9680             fs->group_desc_count * sizeof(int), "free inode count array");
9681
9682         dir_array = (int *) e2fsck_allocate_memory(ctx,
9683            fs->group_desc_count * sizeof(int), "directory count array");
9684
9685         if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
9686             (fs->super->s_inodes_count >
9687              ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
9688                 pctx.num = 3;
9689                 pctx.blk = 1;
9690                 pctx.blk2 = fs->super->s_inodes_count;
9691                 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
9692                 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
9693                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9694
9695                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9696                 return;
9697         }
9698         if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
9699             (fs->super->s_inodes_count >
9700              ext2fs_get_inode_bitmap_end(fs->inode_map))) {
9701                 pctx.num = 4;
9702                 pctx.blk = 1;
9703                 pctx.blk2 = fs->super->s_inodes_count;
9704                 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
9705                 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
9706                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9707
9708                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9709                 return;
9710         }
9711
9712 redo_counts:
9713         had_problem = 0;
9714         save_problem = 0;
9715         pctx.ino = pctx.ino2 = 0;
9716         for (i = 1; i <= fs->super->s_inodes_count; i++) {
9717                 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
9718                 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
9719
9720                 if (actual == bitmap)
9721                         goto do_counts;
9722
9723                 if (!actual && bitmap) {
9724                         /*
9725                          * Inode wasn't used, but marked in bitmap
9726                          */
9727                         problem = PR_5_INODE_UNUSED;
9728                 } else /* if (actual && !bitmap) */ {
9729                         /*
9730                          * Inode used, but not in bitmap
9731                          */
9732                         problem = PR_5_INODE_USED;
9733                 }
9734                 if (pctx.ino == 0) {
9735                         pctx.ino = pctx.ino2 = i;
9736                         save_problem = problem;
9737                 } else {
9738                         if ((problem == save_problem) &&
9739                             (pctx.ino2 == i-1))
9740                                 pctx.ino2++;
9741                         else {
9742                                 print_bitmap_problem(ctx, save_problem, &pctx);
9743                                 pctx.ino = pctx.ino2 = i;
9744                                 save_problem = problem;
9745                         }
9746                 }
9747                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
9748                 had_problem++;
9749
9750 do_counts:
9751                 if (!bitmap) {
9752                         group_free++;
9753                         free_inodes++;
9754                 } else {
9755                         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
9756                                 dirs_count++;
9757                 }
9758                 inodes++;
9759                 if ((inodes == fs->super->s_inodes_per_group) ||
9760                     (i == fs->super->s_inodes_count)) {
9761                         free_array[group] = group_free;
9762                         dir_array[group] = dirs_count;
9763                         group ++;
9764                         inodes = 0;
9765                         group_free = 0;
9766                         dirs_count = 0;
9767                         if (ctx->progress)
9768                                 if ((ctx->progress)(ctx, 5,
9769                                             group + fs->group_desc_count,
9770                                             fs->group_desc_count*2))
9771                                         return;
9772                 }
9773         }
9774         if (pctx.ino)
9775                 print_bitmap_problem(ctx, save_problem, &pctx);
9776
9777         if (had_problem)
9778                 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
9779         else
9780                 fixit = -1;
9781         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
9782
9783         if (fixit == 1) {
9784                 ext2fs_free_inode_bitmap(fs->inode_map);
9785                 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
9786                                                   &fs->inode_map);
9787                 if (retval) {
9788                         clear_problem_context(&pctx);
9789                         fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
9790                         ctx->flags |= E2F_FLAG_ABORT;
9791                         return;
9792                 }
9793                 ext2fs_set_bitmap_padding(fs->inode_map);
9794                 ext2fs_mark_ib_dirty(fs);
9795
9796                 /* redo counts */
9797                 inodes = 0; free_inodes = 0; group_free = 0;
9798                 dirs_count = 0; group = 0;
9799                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
9800                 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
9801                 goto redo_counts;
9802         } else if (fixit == 0)
9803                 ext2fs_unmark_valid(fs);
9804
9805         for (i = 0; i < fs->group_desc_count; i++) {
9806                 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
9807                         pctx.group = i;
9808                         pctx.ino = fs->group_desc[i].bg_free_inodes_count;
9809                         pctx.ino2 = free_array[i];
9810                         if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
9811                                         &pctx)) {
9812                                 fs->group_desc[i].bg_free_inodes_count =
9813                                         free_array[i];
9814                                 ext2fs_mark_super_dirty(fs);
9815                         } else
9816                                 ext2fs_unmark_valid(fs);
9817                 }
9818                 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
9819                         pctx.group = i;
9820                         pctx.ino = fs->group_desc[i].bg_used_dirs_count;
9821                         pctx.ino2 = dir_array[i];
9822
9823                         if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
9824                                         &pctx)) {
9825                                 fs->group_desc[i].bg_used_dirs_count =
9826                                         dir_array[i];
9827                                 ext2fs_mark_super_dirty(fs);
9828                         } else
9829                                 ext2fs_unmark_valid(fs);
9830                 }
9831         }
9832         if (free_inodes != fs->super->s_free_inodes_count) {
9833                 pctx.group = -1;
9834                 pctx.ino = fs->super->s_free_inodes_count;
9835                 pctx.ino2 = free_inodes;
9836
9837                 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
9838                         fs->super->s_free_inodes_count = free_inodes;
9839                         ext2fs_mark_super_dirty(fs);
9840                 } else
9841                         ext2fs_unmark_valid(fs);
9842         }
9843         ext2fs_free_mem(&free_array);
9844         ext2fs_free_mem(&dir_array);
9845 }
9846
9847 static void check_inode_end(e2fsck_t ctx)
9848 {
9849         ext2_filsys fs = ctx->fs;
9850         ext2_ino_t      end, save_inodes_count, i;
9851         struct problem_context  pctx;
9852
9853         clear_problem_context(&pctx);
9854
9855         end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
9856         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
9857                                                      &save_inodes_count);
9858         if (pctx.errcode) {
9859                 pctx.num = 1;
9860                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9861                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9862                 return;
9863         }
9864         if (save_inodes_count == end)
9865                 return;
9866
9867         for (i = save_inodes_count + 1; i <= end; i++) {
9868                 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
9869                         if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
9870                                 for (i = save_inodes_count + 1; i <= end; i++)
9871                                         ext2fs_mark_inode_bitmap(fs->inode_map,
9872                                                                  i);
9873                                 ext2fs_mark_ib_dirty(fs);
9874                         } else
9875                                 ext2fs_unmark_valid(fs);
9876                         break;
9877                 }
9878         }
9879
9880         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
9881                                                      save_inodes_count, 0);
9882         if (pctx.errcode) {
9883                 pctx.num = 2;
9884                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9885                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9886                 return;
9887         }
9888 }
9889
9890 static void check_block_end(e2fsck_t ctx)
9891 {
9892         ext2_filsys fs = ctx->fs;
9893         blk_t   end, save_blocks_count, i;
9894         struct problem_context  pctx;
9895
9896         clear_problem_context(&pctx);
9897
9898         end = fs->block_map->start +
9899                 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
9900         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
9901                                                      &save_blocks_count);
9902         if (pctx.errcode) {
9903                 pctx.num = 3;
9904                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9905                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9906                 return;
9907         }
9908         if (save_blocks_count == end)
9909                 return;
9910
9911         for (i = save_blocks_count + 1; i <= end; i++) {
9912                 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
9913                         if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
9914                                 for (i = save_blocks_count + 1; i <= end; i++)
9915                                         ext2fs_mark_block_bitmap(fs->block_map,
9916                                                                  i);
9917                                 ext2fs_mark_bb_dirty(fs);
9918                         } else
9919                                 ext2fs_unmark_valid(fs);
9920                         break;
9921                 }
9922         }
9923
9924         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
9925                                                      save_blocks_count, 0);
9926         if (pctx.errcode) {
9927                 pctx.num = 4;
9928                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9929                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9930                 return;
9931         }
9932 }
9933
9934 static void e2fsck_pass5(e2fsck_t ctx)
9935 {
9936 #ifdef RESOURCE_TRACK
9937         struct resource_track   rtrack;
9938 #endif
9939         struct problem_context  pctx;
9940
9941 #ifdef MTRACE
9942         mtrace_print("Pass 5");
9943 #endif
9944
9945 #ifdef RESOURCE_TRACK
9946         init_resource_track(&rtrack);
9947 #endif
9948
9949         clear_problem_context(&pctx);
9950
9951         if (!(ctx->options & E2F_OPT_PREEN))
9952                 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
9953
9954         if (ctx->progress)
9955                 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
9956                         return;
9957
9958         e2fsck_read_bitmaps(ctx);
9959
9960         check_block_bitmaps(ctx);
9961         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9962                 return;
9963         check_inode_bitmaps(ctx);
9964         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9965                 return;
9966         check_inode_end(ctx);
9967         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9968                 return;
9969         check_block_end(ctx);
9970         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9971                 return;
9972
9973         ext2fs_free_inode_bitmap(ctx->inode_used_map);
9974         ctx->inode_used_map = 0;
9975         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
9976         ctx->inode_dir_map = 0;
9977         ext2fs_free_block_bitmap(ctx->block_found_map);
9978         ctx->block_found_map = 0;
9979
9980 #ifdef RESOURCE_TRACK
9981         if (ctx->options & E2F_OPT_TIME2) {
9982                 e2fsck_clear_progbar(ctx);
9983                 print_resource_track(_("Pass 5"), &rtrack);
9984         }
9985 #endif
9986 }
9987
9988 /*
9989  * problem.c --- report filesystem problems to the user
9990  */
9991
9992 #define PR_PREEN_OK     0x000001 /* Don't need to do preenhalt */
9993 #define PR_NO_OK        0x000002 /* If user answers no, don't make fs invalid */
9994 #define PR_NO_DEFAULT   0x000004 /* Default to no */
9995 #define PR_MSG_ONLY     0x000008 /* Print message only */
9996
9997 /* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
9998
9999 #define PR_FATAL        0x001000 /* Fatal error */
10000 #define PR_AFTER_CODE   0x002000 /* After asking the first question, */
10001                                  /* ask another */
10002 #define PR_PREEN_NOMSG  0x004000 /* Don't print a message if we're preening */
10003 #define PR_NOCOLLATE    0x008000 /* Don't collate answers for this latch */
10004 #define PR_NO_NOMSG     0x010000 /* Don't print a message if e2fsck -n */
10005 #define PR_PREEN_NO     0x020000 /* Use No as an answer if preening */
10006 #define PR_PREEN_NOHDR  0x040000 /* Don't print the preen header */
10007
10008
10009 #define PROMPT_NONE     0
10010 #define PROMPT_FIX      1
10011 #define PROMPT_CLEAR    2
10012 #define PROMPT_RELOCATE 3
10013 #define PROMPT_ALLOCATE 4
10014 #define PROMPT_EXPAND   5
10015 #define PROMPT_CONNECT  6
10016 #define PROMPT_CREATE   7
10017 #define PROMPT_SALVAGE  8
10018 #define PROMPT_TRUNCATE 9
10019 #define PROMPT_CLEAR_INODE 10
10020 #define PROMPT_ABORT    11
10021 #define PROMPT_SPLIT    12
10022 #define PROMPT_CONTINUE 13
10023 #define PROMPT_CLONE    14
10024 #define PROMPT_DELETE   15
10025 #define PROMPT_SUPPRESS 16
10026 #define PROMPT_UNLINK   17
10027 #define PROMPT_CLEAR_HTREE 18
10028 #define PROMPT_RECREATE 19
10029 #define PROMPT_NULL     20
10030
10031 struct e2fsck_problem {
10032         problem_t       e2p_code;
10033         const char *    e2p_description;
10034         char            prompt;
10035         int             flags;
10036         problem_t       second_code;
10037 };
10038
10039 struct latch_descr {
10040         int             latch_code;
10041         problem_t       question;
10042         problem_t       end_message;
10043         int             flags;
10044 };
10045
10046 /*
10047  * These are the prompts which are used to ask the user if they want
10048  * to fix a problem.
10049  */
10050 static const char * const prompt[] = {
10051         N_("(no prompt)"),      /* 0 */
10052         N_("Fix"),              /* 1 */
10053         N_("Clear"),            /* 2 */
10054         N_("Relocate"),         /* 3 */
10055         N_("Allocate"),         /* 4 */
10056         N_("Expand"),           /* 5 */
10057         N_("Connect to /lost+found"), /* 6 */
10058         N_("Create"),           /* 7 */
10059         N_("Salvage"),          /* 8 */
10060         N_("Truncate"),         /* 9 */
10061         N_("Clear inode"),      /* 10 */
10062         N_("Abort"),            /* 11 */
10063         N_("Split"),            /* 12 */
10064         N_("Continue"),         /* 13 */
10065         N_("Clone multiply-claimed blocks"), /* 14 */
10066         N_("Delete file"),      /* 15 */
10067         N_("Suppress messages"),/* 16 */
10068         N_("Unlink"),           /* 17 */
10069         N_("Clear HTree index"),/* 18 */
10070         N_("Recreate"),         /* 19 */
10071         "",                     /* 20 */
10072 };
10073
10074 /*
10075  * These messages are printed when we are preen mode and we will be
10076  * automatically fixing the problem.
10077  */
10078 static const char * const preen_msg[] = {
10079         N_("(NONE)"),           /* 0 */
10080         N_("FIXED"),            /* 1 */
10081         N_("CLEARED"),          /* 2 */
10082         N_("RELOCATED"),        /* 3 */
10083         N_("ALLOCATED"),        /* 4 */
10084         N_("EXPANDED"),         /* 5 */
10085         N_("RECONNECTED"),      /* 6 */
10086         N_("CREATED"),          /* 7 */
10087         N_("SALVAGED"),         /* 8 */
10088         N_("TRUNCATED"),        /* 9 */
10089         N_("INODE CLEARED"),    /* 10 */
10090         N_("ABORTED"),          /* 11 */
10091         N_("SPLIT"),            /* 12 */
10092         N_("CONTINUING"),       /* 13 */
10093         N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
10094         N_("FILE DELETED"),     /* 15 */
10095         N_("SUPPRESSED"),       /* 16 */
10096         N_("UNLINKED"),         /* 17 */
10097         N_("HTREE INDEX CLEARED"),/* 18 */
10098         N_("WILL RECREATE"),    /* 19 */
10099         "",                     /* 20 */
10100 };
10101
10102 static const struct e2fsck_problem problem_table[] = {
10103
10104         /* Pre-Pass 1 errors */
10105
10106         /* Block bitmap not in group */
10107         { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g.  (@b %b)\n"),
10108           PROMPT_RELOCATE, PR_LATCH_RELOC },
10109
10110         /* Inode bitmap not in group */
10111         { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g.  (@b %b)\n"),
10112           PROMPT_RELOCATE, PR_LATCH_RELOC },
10113
10114         /* Inode table not in group */
10115         { PR_0_ITABLE_NOT_GROUP,
10116           N_("@i table for @g %g is not in @g.  (@b %b)\n"
10117           "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
10118           PROMPT_RELOCATE, PR_LATCH_RELOC },
10119
10120         /* Superblock corrupt */
10121         { PR_0_SB_CORRUPT,
10122           N_("\nThe @S could not be read or does not describe a correct ext2\n"
10123           "@f.  If the @v is valid and it really contains an ext2\n"
10124           "@f (and not swap or ufs or something else), then the @S\n"
10125           "is corrupt, and you might try running e2fsck with an alternate @S:\n"
10126           "    e2fsck -b %S <@v>\n\n"),
10127           PROMPT_NONE, PR_FATAL },
10128
10129         /* Filesystem size is wrong */
10130         { PR_0_FS_SIZE_WRONG,
10131           N_("The @f size (according to the @S) is %b @bs\n"
10132           "The physical size of the @v is %c @bs\n"
10133           "Either the @S or the partition table is likely to be corrupt!\n"),
10134           PROMPT_ABORT, 0 },
10135
10136         /* Fragments not supported */
10137         { PR_0_NO_FRAGMENTS,
10138           N_("@S @b_size = %b, fragsize = %c.\n"
10139           "This version of e2fsck does not support fragment sizes different\n"
10140           "from the @b size.\n"),
10141           PROMPT_NONE, PR_FATAL },
10142
10143           /* Bad blocks_per_group */
10144         { PR_0_BLOCKS_PER_GROUP,
10145           N_("@S @bs_per_group = %b, should have been %c\n"),
10146           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
10147
10148         /* Bad first_data_block */
10149         { PR_0_FIRST_DATA_BLOCK,
10150           N_("@S first_data_@b = %b, should have been %c\n"),
10151           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
10152
10153         /* Adding UUID to filesystem */
10154         { PR_0_ADD_UUID,
10155           N_("@f did not have a UUID; generating one.\n\n"),
10156           PROMPT_NONE, 0 },
10157
10158         /* Relocate hint */
10159         { PR_0_RELOCATE_HINT,
10160           N_("Note: if several inode or block bitmap blocks or part\n"
10161           "of the inode table require relocation, you may wish to try\n"
10162           "running e2fsck with the '-b %S' option first.  The problem\n"
10163           "may lie only with the primary block group descriptors, and\n"
10164           "the backup block group descriptors may be OK.\n\n"),
10165           PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
10166
10167         /* Miscellaneous superblock corruption */
10168         { PR_0_MISC_CORRUPT_SUPER,
10169           N_("Corruption found in @S.  (%s = %N).\n"),
10170           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
10171
10172         /* Error determing physical device size of filesystem */
10173         { PR_0_GETSIZE_ERROR,
10174           N_("Error determining size of the physical @v: %m\n"),
10175           PROMPT_NONE, PR_FATAL },
10176
10177         /* Inode count in superblock is incorrect */
10178         { PR_0_INODE_COUNT_WRONG,
10179           N_("@i count in @S is %i, @s %j.\n"),
10180           PROMPT_FIX, 0 },
10181
10182         { PR_0_HURD_CLEAR_FILETYPE,
10183           N_("The Hurd does not support the filetype feature.\n"),
10184           PROMPT_CLEAR, 0 },
10185
10186         /* Journal inode is invalid */
10187         { PR_0_JOURNAL_BAD_INODE,
10188           N_("@S has an @n ext3 @j (@i %i).\n"),
10189           PROMPT_CLEAR, PR_PREEN_OK },
10190
10191         /* The external journal has (unsupported) multiple filesystems */
10192         { PR_0_JOURNAL_UNSUPP_MULTIFS,
10193           N_("External @j has multiple @f users (unsupported).\n"),
10194           PROMPT_NONE, PR_FATAL },
10195
10196         /* Can't find external journal */
10197         { PR_0_CANT_FIND_JOURNAL,
10198           N_("Can't find external @j\n"),
10199           PROMPT_NONE, PR_FATAL },
10200
10201         /* External journal has bad superblock */
10202         { PR_0_EXT_JOURNAL_BAD_SUPER,
10203           N_("External @j has bad @S\n"),
10204           PROMPT_NONE, PR_FATAL },
10205
10206         /* Superblock has a bad journal UUID */
10207         { PR_0_JOURNAL_BAD_UUID,
10208           N_("External @j does not support this @f\n"),
10209           PROMPT_NONE, PR_FATAL },
10210
10211         /* Journal has an unknown superblock type */
10212         { PR_0_JOURNAL_UNSUPP_SUPER,
10213           N_("Ext3 @j @S is unknown type %N (unsupported).\n"
10214              "It is likely that your copy of e2fsck is old and/or doesn't "
10215              "support this @j format.\n"
10216              "It is also possible the @j @S is corrupt.\n"),
10217           PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
10218
10219         /* Journal superblock is corrupt */
10220         { PR_0_JOURNAL_BAD_SUPER,
10221           N_("Ext3 @j @S is corrupt.\n"),
10222           PROMPT_FIX, PR_PREEN_OK },
10223
10224         /* Superblock flag should be cleared */
10225         { PR_0_JOURNAL_HAS_JOURNAL,
10226           N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
10227           PROMPT_CLEAR, PR_PREEN_OK },
10228
10229         /* Superblock flag is incorrect */
10230         { PR_0_JOURNAL_RECOVER_SET,
10231           N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
10232           PROMPT_CLEAR, PR_PREEN_OK },
10233
10234         /* Journal has data, but recovery flag is clear */
10235         { PR_0_JOURNAL_RECOVERY_CLEAR,
10236           N_("ext3 recovery flag is clear, but @j has data.\n"),
10237           PROMPT_NONE, 0 },
10238
10239         /* Ask if we should clear the journal */
10240         { PR_0_JOURNAL_RESET_JOURNAL,
10241           N_("Clear @j"),
10242           PROMPT_NULL, PR_PREEN_NOMSG },
10243
10244         /* Ask if we should run the journal anyway */
10245         { PR_0_JOURNAL_RUN,
10246           N_("Run @j anyway"),
10247           PROMPT_NULL, 0 },
10248
10249         /* Run the journal by default */
10250         { PR_0_JOURNAL_RUN_DEFAULT,
10251           N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
10252           PROMPT_NONE, 0 },
10253
10254         /* Clearing orphan inode */
10255         { PR_0_ORPHAN_CLEAR_INODE,
10256           N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
10257           PROMPT_NONE, 0 },
10258
10259         /* Illegal block found in orphaned inode */
10260         { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
10261            N_("@I @b #%B (%b) found in @o @i %i.\n"),
10262           PROMPT_NONE, 0 },
10263
10264         /* Already cleared block found in orphaned inode */
10265         { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
10266            N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
10267           PROMPT_NONE, 0 },
10268
10269         /* Illegal orphan inode in superblock */
10270         { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
10271           N_("@I @o @i %i in @S.\n"),
10272           PROMPT_NONE, 0 },
10273
10274         /* Illegal inode in orphaned inode list */
10275         { PR_0_ORPHAN_ILLEGAL_INODE,
10276           N_("@I @i %i in @o @i list.\n"),
10277           PROMPT_NONE, 0 },
10278
10279         /* Filesystem revision is 0, but feature flags are set */
10280         { PR_0_FS_REV_LEVEL,
10281           N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
10282           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
10283
10284         /* Journal superblock has an unknown read-only feature flag set */
10285         { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
10286           N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
10287           PROMPT_ABORT, 0 },
10288
10289         /* Journal superblock has an unknown incompatible feature flag set */
10290         { PR_0_JOURNAL_UNSUPP_INCOMPAT,
10291           N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
10292           PROMPT_ABORT, 0 },
10293
10294         /* Journal has unsupported version number */
10295         { PR_0_JOURNAL_UNSUPP_VERSION,
10296           N_("@j version not supported by this e2fsck.\n"),
10297           PROMPT_ABORT, 0 },
10298
10299         /* Moving journal to hidden file */
10300         { PR_0_MOVE_JOURNAL,
10301           N_("Moving @j from /%s to hidden @i.\n\n"),
10302           PROMPT_NONE, 0 },
10303
10304         /* Error moving journal to hidden file */
10305         { PR_0_ERR_MOVE_JOURNAL,
10306           N_("Error moving @j: %m\n\n"),
10307           PROMPT_NONE, 0 },
10308
10309         /* Clearing V2 journal superblock */
10310         { PR_0_CLEAR_V2_JOURNAL,
10311           N_("Found @n V2 @j @S fields (from V1 @j).\n"
10312              "Clearing fields beyond the V1 @j @S...\n\n"),
10313           PROMPT_NONE, 0 },
10314
10315         /* Backup journal inode blocks */
10316         { PR_0_BACKUP_JNL,
10317           N_("Backing up @j @i @b information.\n\n"),
10318           PROMPT_NONE, 0 },
10319
10320         /* Reserved blocks w/o resize_inode */
10321         { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
10322           N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
10323              "is %N; @s zero.  "),
10324           PROMPT_FIX, 0 },
10325
10326         /* Resize_inode not enabled, but resize inode is non-zero */
10327         { PR_0_CLEAR_RESIZE_INODE,
10328           N_("Resize_@i not enabled, but the resize @i is non-zero.  "),
10329           PROMPT_CLEAR, 0 },
10330
10331         /* Resize inode invalid */
10332         { PR_0_RESIZE_INODE_INVALID,
10333           N_("Resize @i not valid.  "),
10334           PROMPT_RECREATE, 0 },
10335
10336         /* Pass 1 errors */
10337
10338         /* Pass 1: Checking inodes, blocks, and sizes */
10339         { PR_1_PASS_HEADER,
10340           N_("Pass 1: Checking @is, @bs, and sizes\n"),
10341           PROMPT_NONE, 0 },
10342
10343         /* Root directory is not an inode */
10344         { PR_1_ROOT_NO_DIR, N_("@r is not a @d.  "),
10345           PROMPT_CLEAR, 0 },
10346
10347         /* Root directory has dtime set */
10348         { PR_1_ROOT_DTIME,
10349           N_("@r has dtime set (probably due to old mke2fs).  "),
10350           PROMPT_FIX, PR_PREEN_OK },
10351
10352         /* Reserved inode has bad mode */
10353         { PR_1_RESERVED_BAD_MODE,
10354           N_("Reserved @i %i (%Q) has @n mode.  "),
10355           PROMPT_CLEAR, PR_PREEN_OK },
10356
10357         /* Deleted inode has zero dtime */
10358         { PR_1_ZERO_DTIME,
10359           N_("@D @i %i has zero dtime.  "),
10360           PROMPT_FIX, PR_PREEN_OK },
10361
10362         /* Inode in use, but dtime set */
10363         { PR_1_SET_DTIME,
10364           N_("@i %i is in use, but has dtime set.  "),
10365           PROMPT_FIX, PR_PREEN_OK },
10366
10367         /* Zero-length directory */
10368         { PR_1_ZERO_LENGTH_DIR,
10369           N_("@i %i is a @z @d.  "),
10370           PROMPT_CLEAR, PR_PREEN_OK },
10371
10372         /* Block bitmap conflicts with some other fs block */
10373         { PR_1_BB_CONFLICT,
10374           N_("@g %g's @b @B at %b @C.\n"),
10375           PROMPT_RELOCATE, 0 },
10376
10377         /* Inode bitmap conflicts with some other fs block */
10378         { PR_1_IB_CONFLICT,
10379           N_("@g %g's @i @B at %b @C.\n"),
10380           PROMPT_RELOCATE, 0 },
10381
10382         /* Inode table conflicts with some other fs block */
10383         { PR_1_ITABLE_CONFLICT,
10384           N_("@g %g's @i table at %b @C.\n"),
10385           PROMPT_RELOCATE, 0 },
10386
10387         /* Block bitmap is on a bad block */
10388         { PR_1_BB_BAD_BLOCK,
10389           N_("@g %g's @b @B (%b) is bad.  "),
10390           PROMPT_RELOCATE, 0 },
10391
10392         /* Inode bitmap is on a bad block */
10393         { PR_1_IB_BAD_BLOCK,
10394           N_("@g %g's @i @B (%b) is bad.  "),
10395           PROMPT_RELOCATE, 0 },
10396
10397         /* Inode has incorrect i_size */
10398         { PR_1_BAD_I_SIZE,
10399           N_("@i %i, i_size is %Is, @s %N.  "),
10400           PROMPT_FIX, PR_PREEN_OK },
10401
10402         /* Inode has incorrect i_blocks */
10403         { PR_1_BAD_I_BLOCKS,
10404           N_("@i %i, i_@bs is %Ib, @s %N.  "),
10405           PROMPT_FIX, PR_PREEN_OK },
10406
10407         /* Illegal blocknumber in inode */
10408         { PR_1_ILLEGAL_BLOCK_NUM,
10409           N_("@I @b #%B (%b) in @i %i.  "),
10410           PROMPT_CLEAR, PR_LATCH_BLOCK },
10411
10412         /* Block number overlaps fs metadata */
10413         { PR_1_BLOCK_OVERLAPS_METADATA,
10414           N_("@b #%B (%b) overlaps @f metadata in @i %i.  "),
10415           PROMPT_CLEAR, PR_LATCH_BLOCK },
10416
10417         /* Inode has illegal blocks (latch question) */
10418         { PR_1_INODE_BLOCK_LATCH,
10419           N_("@i %i has illegal @b(s).  "),
10420           PROMPT_CLEAR, 0 },
10421
10422         /* Too many bad blocks in inode */
10423         { PR_1_TOO_MANY_BAD_BLOCKS,
10424           N_("Too many illegal @bs in @i %i.\n"),
10425           PROMPT_CLEAR_INODE, PR_NO_OK },
10426
10427         /* Illegal block number in bad block inode */
10428         { PR_1_BB_ILLEGAL_BLOCK_NUM,
10429           N_("@I @b #%B (%b) in bad @b @i.  "),
10430           PROMPT_CLEAR, PR_LATCH_BBLOCK },
10431
10432         /* Bad block inode has illegal blocks (latch question) */
10433         { PR_1_INODE_BBLOCK_LATCH,
10434           N_("Bad @b @i has illegal @b(s).  "),
10435           PROMPT_CLEAR, 0 },
10436
10437         /* Duplicate or bad blocks in use! */
10438         { PR_1_DUP_BLOCKS_PREENSTOP,
10439           N_("Duplicate or bad @b in use!\n"),
10440           PROMPT_NONE, 0 },
10441
10442         /* Bad block used as bad block indirect block */
10443         { PR_1_BBINODE_BAD_METABLOCK,
10444           N_("Bad @b %b used as bad @b @i indirect @b.  "),
10445           PROMPT_CLEAR, PR_LATCH_BBLOCK },
10446
10447         /* Inconsistency can't be fixed prompt */
10448         { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
10449           N_("\nThe bad @b @i has probably been corrupted.  You probably\n"
10450              "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
10451              "in the @f.\n"),
10452           PROMPT_CONTINUE, PR_PREEN_NOMSG },
10453
10454         /* Bad primary block */
10455         { PR_1_BAD_PRIMARY_BLOCK,
10456           N_("\nIf the @b is really bad, the @f can not be fixed.\n"),
10457           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
10458
10459         /* Bad primary block prompt */
10460         { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
10461           N_("You can remove this @b from the bad @b list and hope\n"
10462              "that the @b is really OK.  But there are no guarantees.\n\n"),
10463           PROMPT_CLEAR, PR_PREEN_NOMSG },
10464
10465         /* Bad primary superblock */
10466         { PR_1_BAD_PRIMARY_SUPERBLOCK,
10467           N_("The primary @S (%b) is on the bad @b list.\n"),
10468           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
10469
10470         /* Bad primary block group descriptors */
10471         { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
10472           N_("Block %b in the primary @g descriptors "
10473           "is on the bad @b list\n"),
10474           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
10475
10476         /* Bad superblock in group */
10477         { PR_1_BAD_SUPERBLOCK,
10478           N_("Warning: Group %g's @S (%b) is bad.\n"),
10479           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
10480
10481         /* Bad block group descriptors in group */
10482         { PR_1_BAD_GROUP_DESCRIPTORS,
10483           N_("Warning: Group %g's copy of the @g descriptors has a bad "
10484           "@b (%b).\n"),
10485           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
10486
10487         /* Block claimed for no reason */
10488         { PR_1_PROGERR_CLAIMED_BLOCK,
10489           N_("Programming error?  @b #%b claimed for no reason in "
10490           "process_bad_@b.\n"),
10491           PROMPT_NONE, PR_PREEN_OK },
10492
10493         /* Error allocating blocks for relocating metadata */
10494         { PR_1_RELOC_BLOCK_ALLOCATE,
10495           N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
10496           PROMPT_NONE, PR_PREEN_OK },
10497
10498         /* Error allocating block buffer during relocation process */
10499         { PR_1_RELOC_MEMORY_ALLOCATE,
10500           N_("@A @b buffer for relocating %s\n"),
10501           PROMPT_NONE, PR_PREEN_OK },
10502
10503         /* Relocating metadata group information from X to Y */
10504         { PR_1_RELOC_FROM_TO,
10505           N_("Relocating @g %g's %s from %b to %c...\n"),
10506           PROMPT_NONE, PR_PREEN_OK },
10507
10508         /* Relocating metatdata group information to X */
10509         { PR_1_RELOC_TO,
10510           N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
10511           PROMPT_NONE, PR_PREEN_OK },
10512
10513         /* Block read error during relocation process */
10514         { PR_1_RELOC_READ_ERR,
10515           N_("Warning: could not read @b %b of %s: %m\n"),
10516           PROMPT_NONE, PR_PREEN_OK },
10517
10518         /* Block write error during relocation process */
10519         { PR_1_RELOC_WRITE_ERR,
10520           N_("Warning: could not write @b %b for %s: %m\n"),
10521           PROMPT_NONE, PR_PREEN_OK },
10522
10523         /* Error allocating inode bitmap */
10524         { PR_1_ALLOCATE_IBITMAP_ERROR,
10525           N_("@A @i @B (%N): %m\n"),
10526           PROMPT_NONE, PR_FATAL },
10527
10528         /* Error allocating block bitmap */
10529         { PR_1_ALLOCATE_BBITMAP_ERROR,
10530           N_("@A @b @B (%N): %m\n"),
10531           PROMPT_NONE, PR_FATAL },
10532
10533         /* Error allocating icount structure */
10534         { PR_1_ALLOCATE_ICOUNT,
10535           N_("@A icount link information: %m\n"),
10536           PROMPT_NONE, PR_FATAL },
10537
10538         /* Error allocating dbcount */
10539         { PR_1_ALLOCATE_DBCOUNT,
10540           N_("@A @d @b array: %m\n"),
10541           PROMPT_NONE, PR_FATAL },
10542
10543         /* Error while scanning inodes */
10544         { PR_1_ISCAN_ERROR,
10545           N_("Error while scanning @is (%i): %m\n"),
10546           PROMPT_NONE, PR_FATAL },
10547
10548         /* Error while iterating over blocks */
10549         { PR_1_BLOCK_ITERATE,
10550           N_("Error while iterating over @bs in @i %i: %m\n"),
10551           PROMPT_NONE, PR_FATAL },
10552
10553         /* Error while storing inode count information */
10554         { PR_1_ICOUNT_STORE,
10555           N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
10556           PROMPT_NONE, PR_FATAL },
10557
10558         /* Error while storing directory block information */
10559         { PR_1_ADD_DBLOCK,
10560           N_("Error storing @d @b information "
10561           "(@i=%i, @b=%b, num=%N): %m\n"),
10562           PROMPT_NONE, PR_FATAL },
10563
10564         /* Error while reading inode (for clearing) */
10565         { PR_1_READ_INODE,
10566           N_("Error reading @i %i: %m\n"),
10567           PROMPT_NONE, PR_FATAL },
10568
10569         /* Suppress messages prompt */
10570         { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
10571
10572         /* Imagic flag set on an inode when filesystem doesn't support it */
10573         { PR_1_SET_IMAGIC,
10574           N_("@i %i has imagic flag set.  "),
10575           PROMPT_CLEAR, 0 },
10576
10577         /* Immutable flag set on a device or socket inode */
10578         { PR_1_SET_IMMUTABLE,
10579           N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
10580              "or append-only flag set.  "),
10581           PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
10582
10583         /* Compression flag set on an inode when filesystem doesn't support it */
10584         { PR_1_COMPR_SET,
10585           N_("@i %i has @cion flag set on @f without @cion support.  "),
10586           PROMPT_CLEAR, 0 },
10587
10588         /* Non-zero size for device, fifo or socket inode */
10589         { PR_1_SET_NONZSIZE,
10590           N_("Special (@v/socket/fifo) @i %i has non-zero size.  "),
10591           PROMPT_FIX, PR_PREEN_OK },
10592
10593         /* Filesystem revision is 0, but feature flags are set */
10594         { PR_1_FS_REV_LEVEL,
10595           N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
10596           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
10597
10598         /* Journal inode is not in use, but contains data */
10599         { PR_1_JOURNAL_INODE_NOT_CLEAR,
10600           N_("@j @i is not in use, but contains data.  "),
10601           PROMPT_CLEAR, PR_PREEN_OK },
10602
10603         /* Journal has bad mode */
10604         { PR_1_JOURNAL_BAD_MODE,
10605           N_("@j is not regular file.  "),
10606           PROMPT_FIX, PR_PREEN_OK },
10607
10608         /* Deal with inodes that were part of orphan linked list */
10609         { PR_1_LOW_DTIME,
10610           N_("@i %i was part of the @o @i list.  "),
10611           PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
10612
10613         /* Deal with inodes that were part of corrupted orphan linked
10614            list (latch question) */
10615         { PR_1_ORPHAN_LIST_REFUGEES,
10616           N_("@is that were part of a corrupted orphan linked list found.  "),
10617           PROMPT_FIX, 0 },
10618
10619         /* Error allocating refcount structure */
10620         { PR_1_ALLOCATE_REFCOUNT,
10621           N_("@A refcount structure (%N): %m\n"),
10622           PROMPT_NONE, PR_FATAL },
10623
10624         /* Error reading extended attribute block */
10625         { PR_1_READ_EA_BLOCK,
10626           N_("Error reading @a @b %b for @i %i.  "),
10627           PROMPT_CLEAR, 0 },
10628
10629         /* Invalid extended attribute block */
10630         { PR_1_BAD_EA_BLOCK,
10631           N_("@i %i has a bad @a @b %b.  "),
10632           PROMPT_CLEAR, 0 },
10633
10634         /* Error reading Extended Attribute block while fixing refcount */
10635         { PR_1_EXTATTR_READ_ABORT,
10636           N_("Error reading @a @b %b (%m).  "),
10637           PROMPT_ABORT, 0 },
10638
10639         /* Extended attribute reference count incorrect */
10640         { PR_1_EXTATTR_REFCOUNT,
10641           N_("@a @b %b has reference count %B, @s %N.  "),
10642           PROMPT_FIX, 0 },
10643
10644         /* Error writing Extended Attribute block while fixing refcount */
10645         { PR_1_EXTATTR_WRITE,
10646           N_("Error writing @a @b %b (%m).  "),
10647           PROMPT_ABORT, 0 },
10648
10649         /* Multiple EA blocks not supported */
10650         { PR_1_EA_MULTI_BLOCK,
10651           N_("@a @b %b has h_@bs > 1.  "),
10652           PROMPT_CLEAR, 0},
10653
10654         /* Error allocating EA region allocation structure */
10655         { PR_1_EA_ALLOC_REGION,
10656           N_("@A @a @b %b.  "),
10657           PROMPT_ABORT, 0},
10658
10659         /* Error EA allocation collision */
10660         { PR_1_EA_ALLOC_COLLISION,
10661           N_("@a @b %b is corrupt (allocation collision).  "),
10662           PROMPT_CLEAR, 0},
10663
10664         /* Bad extended attribute name */
10665         { PR_1_EA_BAD_NAME,
10666           N_("@a @b %b is corrupt (@n name).  "),
10667           PROMPT_CLEAR, 0},
10668
10669         /* Bad extended attribute value */
10670         { PR_1_EA_BAD_VALUE,
10671           N_("@a @b %b is corrupt (@n value).  "),
10672           PROMPT_CLEAR, 0},
10673
10674         /* Inode too big (latch question) */
10675         { PR_1_INODE_TOOBIG,
10676           N_("@i %i is too big.  "), PROMPT_TRUNCATE, 0 },
10677
10678         /* Directory too big */
10679         { PR_1_TOOBIG_DIR,
10680           N_("@b #%B (%b) causes @d to be too big.  "),
10681           PROMPT_CLEAR, PR_LATCH_TOOBIG },
10682
10683         /* Regular file too big */
10684         { PR_1_TOOBIG_REG,
10685           N_("@b #%B (%b) causes file to be too big.  "),
10686           PROMPT_CLEAR, PR_LATCH_TOOBIG },
10687
10688         /* Symlink too big */
10689         { PR_1_TOOBIG_SYMLINK,
10690           N_("@b #%B (%b) causes symlink to be too big.  "),
10691           PROMPT_CLEAR, PR_LATCH_TOOBIG },
10692
10693         /* INDEX_FL flag set on a non-HTREE filesystem */
10694         { PR_1_HTREE_SET,
10695           N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
10696           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10697
10698         /* INDEX_FL flag set on a non-directory */
10699         { PR_1_HTREE_NODIR,
10700           N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
10701           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10702
10703         /* Invalid root node in HTREE directory */
10704         { PR_1_HTREE_BADROOT,
10705           N_("@h %i has an @n root node.\n"),
10706           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10707
10708         /* Unsupported hash version in HTREE directory */
10709         { PR_1_HTREE_HASHV,
10710           N_("@h %i has an unsupported hash version (%N)\n"),
10711           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10712
10713         /* Incompatible flag in HTREE root node */
10714         { PR_1_HTREE_INCOMPAT,
10715           N_("@h %i uses an incompatible htree root node flag.\n"),
10716           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10717
10718         /* HTREE too deep */
10719         { PR_1_HTREE_DEPTH,
10720           N_("@h %i has a tree depth (%N) which is too big\n"),
10721           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10722
10723         /* Bad block has indirect block that conflicts with filesystem block */
10724         { PR_1_BB_FS_BLOCK,
10725           N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
10726              "@f metadata.  "),
10727           PROMPT_CLEAR, PR_LATCH_BBLOCK },
10728
10729         /* Resize inode failed */
10730         { PR_1_RESIZE_INODE_CREATE,
10731           N_("Resize @i (re)creation failed: %m."),
10732           PROMPT_ABORT, 0 },
10733
10734         /* invalid inode->i_extra_isize */
10735         { PR_1_EXTRA_ISIZE,
10736           N_("@i %i has a extra size (%IS) which is @n\n"),
10737           PROMPT_FIX, PR_PREEN_OK },
10738
10739         /* invalid ea entry->e_name_len */
10740         { PR_1_ATTR_NAME_LEN,
10741           N_("@a in @i %i has a namelen (%N) which is @n\n"),
10742           PROMPT_CLEAR, PR_PREEN_OK },
10743
10744         /* invalid ea entry->e_value_size */
10745         { PR_1_ATTR_VALUE_SIZE,
10746           N_("@a in @i %i has a value size (%N) which is @n\n"),
10747           PROMPT_CLEAR, PR_PREEN_OK },
10748
10749         /* invalid ea entry->e_value_offs */
10750         { PR_1_ATTR_VALUE_OFFSET,
10751           N_("@a in @i %i has a value offset (%N) which is @n\n"),
10752           PROMPT_CLEAR, PR_PREEN_OK },
10753
10754         /* invalid ea entry->e_value_block */
10755         { PR_1_ATTR_VALUE_BLOCK,
10756           N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
10757           PROMPT_CLEAR, PR_PREEN_OK },
10758
10759         /* invalid ea entry->e_hash */
10760         { PR_1_ATTR_HASH,
10761           N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
10762           PROMPT_CLEAR, PR_PREEN_OK },
10763
10764         /* Pass 1b errors */
10765
10766         /* Pass 1B: Rescan for duplicate/bad blocks */
10767         { PR_1B_PASS_HEADER,
10768           N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
10769           "Pass 1B: Rescanning for @m @bs\n"),
10770           PROMPT_NONE, 0 },
10771
10772         /* Duplicate/bad block(s) header */
10773         { PR_1B_DUP_BLOCK_HEADER,
10774           N_("@m @b(s) in @i %i:"),
10775           PROMPT_NONE, 0 },
10776
10777         /* Duplicate/bad block(s) in inode */
10778         { PR_1B_DUP_BLOCK,
10779           " %b",
10780           PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
10781
10782         /* Duplicate/bad block(s) end */
10783         { PR_1B_DUP_BLOCK_END,
10784           "\n",
10785           PROMPT_NONE, PR_PREEN_NOHDR },
10786
10787         /* Error while scanning inodes */
10788         { PR_1B_ISCAN_ERROR,
10789           N_("Error while scanning inodes (%i): %m\n"),
10790           PROMPT_NONE, PR_FATAL },
10791
10792         /* Error allocating inode bitmap */
10793         { PR_1B_ALLOCATE_IBITMAP_ERROR,
10794           N_("@A @i @B (@i_dup_map): %m\n"),
10795           PROMPT_NONE, PR_FATAL },
10796
10797         /* Error while iterating over blocks */
10798         { PR_1B_BLOCK_ITERATE,
10799           N_("Error while iterating over @bs in @i %i (%s): %m\n"),
10800           PROMPT_NONE, 0 },
10801
10802         /* Error adjusting EA refcount */
10803         { PR_1B_ADJ_EA_REFCOUNT,
10804           N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
10805           PROMPT_NONE, 0 },
10806
10807
10808         /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
10809         { PR_1C_PASS_HEADER,
10810           N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
10811           PROMPT_NONE, 0 },
10812
10813
10814         /* Pass 1D: Reconciling multiply-claimed blocks */
10815         { PR_1D_PASS_HEADER,
10816           N_("Pass 1D: Reconciling @m @bs\n"),
10817           PROMPT_NONE, 0 },
10818
10819         /* File has duplicate blocks */
10820         { PR_1D_DUP_FILE,
10821           N_("File %Q (@i #%i, mod time %IM) \n"
10822           "  has %B @m @b(s), shared with %N file(s):\n"),
10823           PROMPT_NONE, 0 },
10824
10825         /* List of files sharing duplicate blocks */
10826         { PR_1D_DUP_FILE_LIST,
10827           N_("\t%Q (@i #%i, mod time %IM)\n"),
10828           PROMPT_NONE, 0 },
10829
10830         /* File sharing blocks with filesystem metadata  */
10831         { PR_1D_SHARE_METADATA,
10832           N_("\t<@f metadata>\n"),
10833           PROMPT_NONE, 0 },
10834
10835         /* Report of how many duplicate/bad inodes */
10836         { PR_1D_NUM_DUP_INODES,
10837           N_("(There are %N @is containing @m @bs.)\n\n"),
10838           PROMPT_NONE, 0 },
10839
10840         /* Duplicated blocks already reassigned or cloned. */
10841         { PR_1D_DUP_BLOCKS_DEALT,
10842           N_("@m @bs already reassigned or cloned.\n\n"),
10843           PROMPT_NONE, 0 },
10844
10845         /* Clone duplicate/bad blocks? */
10846         { PR_1D_CLONE_QUESTION,
10847           "", PROMPT_CLONE, PR_NO_OK },
10848
10849         /* Delete file? */
10850         { PR_1D_DELETE_QUESTION,
10851           "", PROMPT_DELETE, 0 },
10852
10853         /* Couldn't clone file (error) */
10854         { PR_1D_CLONE_ERROR,
10855           N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
10856
10857         /* Pass 2 errors */
10858
10859         /* Pass 2: Checking directory structure */
10860         { PR_2_PASS_HEADER,
10861           N_("Pass 2: Checking @d structure\n"),
10862           PROMPT_NONE, 0 },
10863
10864         /* Bad inode number for '.' */
10865         { PR_2_BAD_INODE_DOT,
10866           N_("@n @i number for '.' in @d @i %i.\n"),
10867           PROMPT_FIX, 0 },
10868
10869         /* Directory entry has bad inode number */
10870         { PR_2_BAD_INO,
10871           N_("@E has @n @i #: %Di.\n"),
10872           PROMPT_CLEAR, 0 },
10873
10874         /* Directory entry has deleted or unused inode */
10875         { PR_2_UNUSED_INODE,
10876           N_("@E has @D/unused @i %Di.  "),
10877           PROMPT_CLEAR, PR_PREEN_OK },
10878
10879         /* Directry entry is link to '.' */
10880         { PR_2_LINK_DOT,
10881           N_("@E @L to '.'  "),
10882           PROMPT_CLEAR, 0 },
10883
10884         /* Directory entry points to inode now located in a bad block */
10885         { PR_2_BB_INODE,
10886           N_("@E points to @i (%Di) located in a bad @b.\n"),
10887           PROMPT_CLEAR, 0 },
10888
10889         /* Directory entry contains a link to a directory */
10890         { PR_2_LINK_DIR,
10891           N_("@E @L to @d %P (%Di).\n"),
10892           PROMPT_CLEAR, 0 },
10893
10894         /* Directory entry contains a link to the root directry */
10895         { PR_2_LINK_ROOT,
10896           N_("@E @L to the @r.\n"),
10897           PROMPT_CLEAR, 0 },
10898
10899         /* Directory entry has illegal characters in its name */
10900         { PR_2_BAD_NAME,
10901           N_("@E has illegal characters in its name.\n"),
10902           PROMPT_FIX, 0 },
10903
10904         /* Missing '.' in directory inode */
10905         { PR_2_MISSING_DOT,
10906           N_("Missing '.' in @d @i %i.\n"),
10907           PROMPT_FIX, 0 },
10908
10909         /* Missing '..' in directory inode */
10910         { PR_2_MISSING_DOT_DOT,
10911           N_("Missing '..' in @d @i %i.\n"),
10912           PROMPT_FIX, 0 },
10913
10914         /* First entry in directory inode doesn't contain '.' */
10915         { PR_2_1ST_NOT_DOT,
10916           N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
10917           PROMPT_FIX, 0 },
10918
10919         /* Second entry in directory inode doesn't contain '..' */
10920         { PR_2_2ND_NOT_DOT_DOT,
10921           N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
10922           PROMPT_FIX, 0 },
10923
10924         /* i_faddr should be zero */
10925         { PR_2_FADDR_ZERO,
10926           N_("i_faddr @F %IF, @s zero.\n"),
10927           PROMPT_CLEAR, 0 },
10928
10929         /* i_file_acl should be zero */
10930         { PR_2_FILE_ACL_ZERO,
10931           N_("i_file_acl @F %If, @s zero.\n"),
10932           PROMPT_CLEAR, 0 },
10933
10934         /* i_dir_acl should be zero */
10935         { PR_2_DIR_ACL_ZERO,
10936           N_("i_dir_acl @F %Id, @s zero.\n"),
10937           PROMPT_CLEAR, 0 },
10938
10939         /* i_frag should be zero */
10940         { PR_2_FRAG_ZERO,
10941           N_("i_frag @F %N, @s zero.\n"),
10942           PROMPT_CLEAR, 0 },
10943
10944         /* i_fsize should be zero */
10945         { PR_2_FSIZE_ZERO,
10946           N_("i_fsize @F %N, @s zero.\n"),
10947           PROMPT_CLEAR, 0 },
10948
10949         /* inode has bad mode */
10950         { PR_2_BAD_MODE,
10951           N_("@i %i (%Q) has @n mode (%Im).\n"),
10952           PROMPT_CLEAR, 0 },
10953
10954         /* directory corrupted */
10955         { PR_2_DIR_CORRUPTED,
10956           N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
10957           PROMPT_SALVAGE, 0 },
10958
10959         /* filename too long */
10960         { PR_2_FILENAME_LONG,
10961           N_("@d @i %i, @b %B, offset %N: filename too long\n"),
10962           PROMPT_TRUNCATE, 0 },
10963
10964         /* Directory inode has a missing block (hole) */
10965         { PR_2_DIRECTORY_HOLE,
10966           N_("@d @i %i has an unallocated @b #%B.  "),
10967           PROMPT_ALLOCATE, 0 },
10968
10969         /* '.' is not NULL terminated */
10970         { PR_2_DOT_NULL_TERM,
10971           N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
10972           PROMPT_FIX, 0 },
10973
10974         /* '..' is not NULL terminated */
10975         { PR_2_DOT_DOT_NULL_TERM,
10976           N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
10977           PROMPT_FIX, 0 },
10978
10979         /* Illegal character device inode */
10980         { PR_2_BAD_CHAR_DEV,
10981           N_("@i %i (%Q) is an @I character @v.\n"),
10982           PROMPT_CLEAR, 0 },
10983
10984         /* Illegal block device inode */
10985         { PR_2_BAD_BLOCK_DEV,
10986           N_("@i %i (%Q) is an @I @b @v.\n"),
10987           PROMPT_CLEAR, 0 },
10988
10989         /* Duplicate '.' entry */
10990         { PR_2_DUP_DOT,
10991           N_("@E is duplicate '.' @e.\n"),
10992           PROMPT_FIX, 0 },
10993
10994         /* Duplicate '..' entry */
10995         { PR_2_DUP_DOT_DOT,
10996           N_("@E is duplicate '..' @e.\n"),
10997           PROMPT_FIX, 0 },
10998
10999         /* Internal error: couldn't find dir_info */
11000         { PR_2_NO_DIRINFO,
11001           N_("Internal error: couldn't find dir_info for %i.\n"),
11002           PROMPT_NONE, PR_FATAL },
11003
11004         /* Final rec_len is wrong */
11005         { PR_2_FINAL_RECLEN,
11006           N_("@E has rec_len of %Dr, @s %N.\n"),
11007           PROMPT_FIX, 0 },
11008
11009         /* Error allocating icount structure */
11010         { PR_2_ALLOCATE_ICOUNT,
11011           N_("@A icount structure: %m\n"),
11012           PROMPT_NONE, PR_FATAL },
11013
11014         /* Error iterating over directory blocks */
11015         { PR_2_DBLIST_ITERATE,
11016           N_("Error iterating over @d @bs: %m\n"),
11017           PROMPT_NONE, PR_FATAL },
11018
11019         /* Error reading directory block */
11020         { PR_2_READ_DIRBLOCK,
11021           N_("Error reading @d @b %b (@i %i): %m\n"),
11022           PROMPT_CONTINUE, 0 },
11023
11024         /* Error writing directory block */
11025         { PR_2_WRITE_DIRBLOCK,
11026           N_("Error writing @d @b %b (@i %i): %m\n"),
11027           PROMPT_CONTINUE, 0 },
11028
11029         /* Error allocating new directory block */
11030         { PR_2_ALLOC_DIRBOCK,
11031           N_("@A new @d @b for @i %i (%s): %m\n"),
11032           PROMPT_NONE, 0 },
11033
11034         /* Error deallocating inode */
11035         { PR_2_DEALLOC_INODE,
11036           N_("Error deallocating @i %i: %m\n"),
11037           PROMPT_NONE, PR_FATAL },
11038
11039         /* Directory entry for '.' is big.  Split? */
11040         { PR_2_SPLIT_DOT,
11041           N_("@d @e for '.' is big.  "),
11042           PROMPT_SPLIT, PR_NO_OK },
11043
11044         /* Illegal FIFO inode */
11045         { PR_2_BAD_FIFO,
11046           N_("@i %i (%Q) is an @I FIFO.\n"),
11047           PROMPT_CLEAR, 0 },
11048
11049         /* Illegal socket inode */
11050         { PR_2_BAD_SOCKET,
11051           N_("@i %i (%Q) is an @I socket.\n"),
11052           PROMPT_CLEAR, 0 },
11053
11054         /* Directory filetype not set */
11055         { PR_2_SET_FILETYPE,
11056           N_("Setting filetype for @E to %N.\n"),
11057           PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
11058
11059         /* Directory filetype incorrect */
11060         { PR_2_BAD_FILETYPE,
11061           N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
11062           PROMPT_FIX, 0 },
11063
11064         /* Directory filetype set on filesystem */
11065         { PR_2_CLEAR_FILETYPE,
11066           N_("@E has filetype set.\n"),
11067           PROMPT_CLEAR, PR_PREEN_OK },
11068
11069         /* Directory filename is null */
11070         { PR_2_NULL_NAME,
11071           N_("@E has a @z name.\n"),
11072           PROMPT_CLEAR, 0 },
11073
11074         /* Invalid symlink */
11075         { PR_2_INVALID_SYMLINK,
11076           N_("Symlink %Q (@i #%i) is @n.\n"),
11077           PROMPT_CLEAR, 0 },
11078
11079         /* i_file_acl (extended attribute block) is bad */
11080         { PR_2_FILE_ACL_BAD,
11081           N_("@a @b @F @n (%If).\n"),
11082           PROMPT_CLEAR, 0 },
11083
11084         /* Filesystem contains large files, but has no such flag in sb */
11085         { PR_2_FEATURE_LARGE_FILES,
11086           N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
11087           PROMPT_FIX, 0 },
11088
11089         /* Node in HTREE directory not referenced */
11090         { PR_2_HTREE_NOTREF,
11091           N_("@p @h %d: node (%B) not referenced\n"),
11092           PROMPT_NONE, 0 },
11093
11094         /* Node in HTREE directory referenced twice */
11095         { PR_2_HTREE_DUPREF,
11096           N_("@p @h %d: node (%B) referenced twice\n"),
11097           PROMPT_NONE, 0 },
11098
11099         /* Node in HTREE directory has bad min hash */
11100         { PR_2_HTREE_MIN_HASH,
11101           N_("@p @h %d: node (%B) has bad min hash\n"),
11102           PROMPT_NONE, 0 },
11103
11104         /* Node in HTREE directory has bad max hash */
11105         { PR_2_HTREE_MAX_HASH,
11106           N_("@p @h %d: node (%B) has bad max hash\n"),
11107           PROMPT_NONE, 0 },
11108
11109         /* Clear invalid HTREE directory */
11110         { PR_2_HTREE_CLEAR,
11111           N_("@n @h %d (%q).  "), PROMPT_CLEAR, 0 },
11112
11113         /* Bad block in htree interior node */
11114         { PR_2_HTREE_BADBLK,
11115           N_("@p @h %d (%q): bad @b number %b.\n"),
11116           PROMPT_CLEAR_HTREE, 0 },
11117
11118         /* Error adjusting EA refcount */
11119         { PR_2_ADJ_EA_REFCOUNT,
11120           N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
11121           PROMPT_NONE, PR_FATAL },
11122
11123         /* Invalid HTREE root node */
11124         { PR_2_HTREE_BAD_ROOT,
11125           N_("@p @h %d: root node is @n\n"),
11126           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11127
11128         /* Invalid HTREE limit */
11129         { PR_2_HTREE_BAD_LIMIT,
11130           N_("@p @h %d: node (%B) has @n limit (%N)\n"),
11131           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11132
11133         /* Invalid HTREE count */
11134         { PR_2_HTREE_BAD_COUNT,
11135           N_("@p @h %d: node (%B) has @n count (%N)\n"),
11136           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11137
11138         /* HTREE interior node has out-of-order hashes in table */
11139         { PR_2_HTREE_HASH_ORDER,
11140           N_("@p @h %d: node (%B) has an unordered hash table\n"),
11141           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11142
11143         /* Node in HTREE directory has invalid depth */
11144         { PR_2_HTREE_BAD_DEPTH,
11145           N_("@p @h %d: node (%B) has @n depth\n"),
11146           PROMPT_NONE, 0 },
11147
11148         /* Duplicate directory entry found */
11149         { PR_2_DUPLICATE_DIRENT,
11150           N_("Duplicate @E found.  "),
11151           PROMPT_CLEAR, 0 },
11152
11153         /* Non-unique filename found */
11154         { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
11155           N_("@E has a non-unique filename.\nRename to %s"),
11156           PROMPT_NULL, 0 },
11157
11158         /* Duplicate directory entry found */
11159         { PR_2_REPORT_DUP_DIRENT,
11160           N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
11161           PROMPT_NONE, 0 },
11162
11163         /* Pass 3 errors */
11164
11165         /* Pass 3: Checking directory connectivity */
11166         { PR_3_PASS_HEADER,
11167           N_("Pass 3: Checking @d connectivity\n"),
11168           PROMPT_NONE, 0 },
11169
11170         /* Root inode not allocated */
11171         { PR_3_NO_ROOT_INODE,
11172           N_("@r not allocated.  "),
11173           PROMPT_ALLOCATE, 0 },
11174
11175         /* No room in lost+found */
11176         { PR_3_EXPAND_LF_DIR,
11177           N_("No room in @l @d.  "),
11178           PROMPT_EXPAND, 0 },
11179
11180         /* Unconnected directory inode */
11181         { PR_3_UNCONNECTED_DIR,
11182           N_("Unconnected @d @i %i (%p)\n"),
11183           PROMPT_CONNECT, 0 },
11184
11185         /* /lost+found not found */
11186         { PR_3_NO_LF_DIR,
11187           N_("/@l not found.  "),
11188           PROMPT_CREATE, PR_PREEN_OK },
11189
11190         /* .. entry is incorrect */
11191         { PR_3_BAD_DOT_DOT,
11192           N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
11193           PROMPT_FIX, 0 },
11194
11195         /* Bad or non-existent /lost+found.  Cannot reconnect */
11196         { PR_3_NO_LPF,
11197           N_("Bad or non-existent /@l.  Cannot reconnect.\n"),
11198           PROMPT_NONE, 0 },
11199
11200         /* Could not expand /lost+found */
11201         { PR_3_CANT_EXPAND_LPF,
11202           N_("Could not expand /@l: %m\n"),
11203           PROMPT_NONE, 0 },
11204
11205         /* Could not reconnect inode */
11206         { PR_3_CANT_RECONNECT,
11207           N_("Could not reconnect %i: %m\n"),
11208           PROMPT_NONE, 0 },
11209
11210         /* Error while trying to find /lost+found */
11211         { PR_3_ERR_FIND_LPF,
11212           N_("Error while trying to find /@l: %m\n"),
11213           PROMPT_NONE, 0 },
11214
11215         /* Error in ext2fs_new_block while creating /lost+found */
11216         { PR_3_ERR_LPF_NEW_BLOCK,
11217           N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
11218           PROMPT_NONE, 0 },
11219
11220         /* Error in ext2fs_new_inode while creating /lost+found */
11221         { PR_3_ERR_LPF_NEW_INODE,
11222           N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
11223           PROMPT_NONE, 0 },
11224
11225         /* Error in ext2fs_new_dir_block while creating /lost+found */
11226         { PR_3_ERR_LPF_NEW_DIR_BLOCK,
11227           N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
11228           PROMPT_NONE, 0 },
11229
11230         /* Error while writing directory block for /lost+found */
11231         { PR_3_ERR_LPF_WRITE_BLOCK,
11232           N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
11233           PROMPT_NONE, 0 },
11234
11235         /* Error while adjusting inode count */
11236         { PR_3_ADJUST_INODE,
11237           N_("Error while adjusting @i count on @i %i\n"),
11238           PROMPT_NONE, 0 },
11239
11240         /* Couldn't fix parent directory -- error */
11241         { PR_3_FIX_PARENT_ERR,
11242           N_("Couldn't fix parent of @i %i: %m\n\n"),
11243           PROMPT_NONE, 0 },
11244
11245         /* Couldn't fix parent directory -- couldn't find it */
11246         { PR_3_FIX_PARENT_NOFIND,
11247           N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
11248           PROMPT_NONE, 0 },
11249
11250         /* Error allocating inode bitmap */
11251         { PR_3_ALLOCATE_IBITMAP_ERROR,
11252           N_("@A @i @B (%N): %m\n"),
11253           PROMPT_NONE, PR_FATAL },
11254
11255         /* Error creating root directory */
11256         { PR_3_CREATE_ROOT_ERROR,
11257           N_("Error creating root @d (%s): %m\n"),
11258           PROMPT_NONE, PR_FATAL },
11259
11260         /* Error creating lost and found directory */
11261         { PR_3_CREATE_LPF_ERROR,
11262           N_("Error creating /@l @d (%s): %m\n"),
11263           PROMPT_NONE, PR_FATAL },
11264
11265         /* Root inode is not directory; aborting */
11266         { PR_3_ROOT_NOT_DIR_ABORT,
11267           N_("@r is not a @d; aborting.\n"),
11268           PROMPT_NONE, PR_FATAL },
11269
11270         /* Cannot proceed without a root inode. */
11271         { PR_3_NO_ROOT_INODE_ABORT,
11272           N_("Cannot proceed without a @r.\n"),
11273           PROMPT_NONE, PR_FATAL },
11274
11275         /* Internal error: couldn't find dir_info */
11276         { PR_3_NO_DIRINFO,
11277           N_("Internal error: couldn't find dir_info for %i.\n"),
11278           PROMPT_NONE, PR_FATAL },
11279
11280         /* Lost+found not a directory */
11281         { PR_3_LPF_NOTDIR,
11282           N_("/@l is not a @d (ino=%i)\n"),
11283           PROMPT_UNLINK, 0 },
11284
11285         /* Pass 3A Directory Optimization       */
11286
11287         /* Pass 3A: Optimizing directories */
11288         { PR_3A_PASS_HEADER,
11289           N_("Pass 3A: Optimizing directories\n"),
11290           PROMPT_NONE, PR_PREEN_NOMSG },
11291
11292         /* Error iterating over directories */
11293         { PR_3A_OPTIMIZE_ITER,
11294           N_("Failed to create dirs_to_hash iterator: %m"),
11295           PROMPT_NONE, 0 },
11296
11297         /* Error rehash directory */
11298         { PR_3A_OPTIMIZE_DIR_ERR,
11299           N_("Failed to optimize directory %q (%d): %m"),
11300           PROMPT_NONE, 0 },
11301
11302         /* Rehashing dir header */
11303         { PR_3A_OPTIMIZE_DIR_HEADER,
11304           N_("Optimizing directories: "),
11305           PROMPT_NONE, PR_MSG_ONLY },
11306
11307         /* Rehashing directory %d */
11308         { PR_3A_OPTIMIZE_DIR,
11309           " %d",
11310           PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
11311
11312         /* Rehashing dir end */
11313         { PR_3A_OPTIMIZE_DIR_END,
11314           "\n",
11315           PROMPT_NONE, PR_PREEN_NOHDR },
11316
11317         /* Pass 4 errors */
11318
11319         /* Pass 4: Checking reference counts */
11320         { PR_4_PASS_HEADER,
11321           N_("Pass 4: Checking reference counts\n"),
11322           PROMPT_NONE, 0 },
11323
11324         /* Unattached zero-length inode */
11325         { PR_4_ZERO_LEN_INODE,
11326           N_("@u @z @i %i.  "),
11327           PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
11328
11329         /* Unattached inode */
11330         { PR_4_UNATTACHED_INODE,
11331           N_("@u @i %i\n"),
11332           PROMPT_CONNECT, 0 },
11333
11334         /* Inode ref count wrong */
11335         { PR_4_BAD_REF_COUNT,
11336           N_("@i %i ref count is %Il, @s %N.  "),
11337           PROMPT_FIX, PR_PREEN_OK },
11338
11339         { PR_4_INCONSISTENT_COUNT,
11340           N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
11341           "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
11342           "@i_link_info[%i] is %N, @i.i_links_count is %Il.  "
11343           "They @s the same!\n"),
11344           PROMPT_NONE, 0 },
11345
11346         /* Pass 5 errors */
11347
11348         /* Pass 5: Checking group summary information */
11349         { PR_5_PASS_HEADER,
11350           N_("Pass 5: Checking @g summary information\n"),
11351           PROMPT_NONE, 0 },
11352
11353         /* Padding at end of inode bitmap is not set. */
11354         { PR_5_INODE_BMAP_PADDING,
11355           N_("Padding at end of @i @B is not set. "),
11356           PROMPT_FIX, PR_PREEN_OK },
11357
11358         /* Padding at end of block bitmap is not set. */
11359         { PR_5_BLOCK_BMAP_PADDING,
11360           N_("Padding at end of @b @B is not set. "),
11361           PROMPT_FIX, PR_PREEN_OK },
11362
11363         /* Block bitmap differences header */
11364         { PR_5_BLOCK_BITMAP_HEADER,
11365           N_("@b @B differences: "),
11366           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
11367
11368         /* Block not used, but marked in bitmap */
11369         { PR_5_BLOCK_UNUSED,
11370           " -%b",
11371           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11372
11373         /* Block used, but not marked used in bitmap */
11374         { PR_5_BLOCK_USED,
11375           " +%b",
11376           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11377
11378         /* Block bitmap differences end */
11379         { PR_5_BLOCK_BITMAP_END,
11380           "\n",
11381           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11382
11383         /* Inode bitmap differences header */
11384         { PR_5_INODE_BITMAP_HEADER,
11385           N_("@i @B differences: "),
11386           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
11387
11388         /* Inode not used, but marked in bitmap */
11389         { PR_5_INODE_UNUSED,
11390           " -%i",
11391           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11392
11393         /* Inode used, but not marked used in bitmap */
11394         { PR_5_INODE_USED,
11395           " +%i",
11396           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11397
11398         /* Inode bitmap differences end */
11399         { PR_5_INODE_BITMAP_END,
11400           "\n",
11401           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11402
11403         /* Free inodes count for group wrong */
11404         { PR_5_FREE_INODE_COUNT_GROUP,
11405           N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
11406           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11407
11408         /* Directories count for group wrong */
11409         { PR_5_FREE_DIR_COUNT_GROUP,
11410           N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
11411           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11412
11413         /* Free inodes count wrong */
11414         { PR_5_FREE_INODE_COUNT,
11415           N_("Free @is count wrong (%i, counted=%j).\n"),
11416           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11417
11418         /* Free blocks count for group wrong */
11419         { PR_5_FREE_BLOCK_COUNT_GROUP,
11420           N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
11421           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11422
11423         /* Free blocks count wrong */
11424         { PR_5_FREE_BLOCK_COUNT,
11425           N_("Free @bs count wrong (%b, counted=%c).\n"),
11426           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11427
11428         /* Programming error: bitmap endpoints don't match */
11429         { PR_5_BMAP_ENDPOINTS,
11430           N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
11431           "match calculated @B endpoints (%i, %j)\n"),
11432           PROMPT_NONE, PR_FATAL },
11433
11434         /* Internal error: fudging end of bitmap */
11435         { PR_5_FUDGE_BITMAP_ERROR,
11436           N_("Internal error: fudging end of bitmap (%N)\n"),
11437           PROMPT_NONE, PR_FATAL },
11438
11439         /* Error copying in replacement inode bitmap */
11440         { PR_5_COPY_IBITMAP_ERROR,
11441           N_("Error copying in replacement @i @B: %m\n"),
11442           PROMPT_NONE, PR_FATAL },
11443
11444         /* Error copying in replacement block bitmap */
11445         { PR_5_COPY_BBITMAP_ERROR,
11446           N_("Error copying in replacement @b @B: %m\n"),
11447           PROMPT_NONE, PR_FATAL },
11448
11449         /* Block range not used, but marked in bitmap */
11450         { PR_5_BLOCK_RANGE_UNUSED,
11451           " -(%b--%c)",
11452           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11453
11454         /* Block range used, but not marked used in bitmap */
11455         { PR_5_BLOCK_RANGE_USED,
11456           " +(%b--%c)",
11457           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11458
11459         /* Inode range not used, but marked in bitmap */
11460         { PR_5_INODE_RANGE_UNUSED,
11461           " -(%i--%j)",
11462           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11463
11464         /* Inode range used, but not marked used in bitmap */
11465         { PR_5_INODE_RANGE_USED,
11466           " +(%i--%j)",
11467           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11468
11469         { 0 }
11470 };
11471
11472 /*
11473  * This is the latch flags register.  It allows several problems to be
11474  * "latched" together.  This means that the user has to answer but one
11475  * question for the set of problems, and all of the associated
11476  * problems will be either fixed or not fixed.
11477  */
11478 static struct latch_descr pr_latch_info[] = {
11479         { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
11480         { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
11481         { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
11482         { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
11483         { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
11484         { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
11485         { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
11486         { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
11487         { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
11488         { -1, 0, 0 },
11489 };
11490
11491 static const struct e2fsck_problem *find_problem(problem_t code)
11492 {
11493         int     i;
11494
11495         for (i=0; problem_table[i].e2p_code; i++) {
11496                 if (problem_table[i].e2p_code == code)
11497                         return &problem_table[i];
11498         }
11499         return 0;
11500 }
11501
11502 static struct latch_descr *find_latch(int code)
11503 {
11504         int     i;
11505
11506         for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
11507                 if (pr_latch_info[i].latch_code == code)
11508                         return &pr_latch_info[i];
11509         }
11510         return 0;
11511 }
11512
11513 int end_problem_latch(e2fsck_t ctx, int mask)
11514 {
11515         struct latch_descr *ldesc;
11516         struct problem_context pctx;
11517         int answer = -1;
11518
11519         ldesc = find_latch(mask);
11520         if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
11521                 clear_problem_context(&pctx);
11522                 answer = fix_problem(ctx, ldesc->end_message, &pctx);
11523         }
11524         ldesc->flags &= ~(PRL_VARIABLE);
11525         return answer;
11526 }
11527
11528 int set_latch_flags(int mask, int setflags, int clearflags)
11529 {
11530         struct latch_descr *ldesc;
11531
11532         ldesc = find_latch(mask);
11533         if (!ldesc)
11534                 return -1;
11535         ldesc->flags |= setflags;
11536         ldesc->flags &= ~clearflags;
11537         return 0;
11538 }
11539
11540 void clear_problem_context(struct problem_context *ctx)
11541 {
11542         memset(ctx, 0, sizeof(struct problem_context));
11543         ctx->blkcount = -1;
11544         ctx->group = -1;
11545 }
11546
11547 int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
11548 {
11549         ext2_filsys fs = ctx->fs;
11550         const struct e2fsck_problem *ptr;
11551         struct latch_descr *ldesc = 0;
11552         const char *message;
11553         int             def_yn, answer, ans;
11554         int             print_answer = 0;
11555         int             suppress = 0;
11556
11557         ptr = find_problem(code);
11558         if (!ptr) {
11559                 printf(_("Unhandled error code (0x%x)!\n"), code);
11560                 return 0;
11561         }
11562         def_yn = 1;
11563         if ((ptr->flags & PR_NO_DEFAULT) ||
11564             ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
11565             (ctx->options & E2F_OPT_NO))
11566                 def_yn= 0;
11567
11568         /*
11569          * Do special latch processing.  This is where we ask the
11570          * latch question, if it exists
11571          */
11572         if (ptr->flags & PR_LATCH_MASK) {
11573                 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
11574                 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
11575                         ans = fix_problem(ctx, ldesc->question, pctx);
11576                         if (ans == 1)
11577                                 ldesc->flags |= PRL_YES;
11578                         if (ans == 0)
11579                                 ldesc->flags |= PRL_NO;
11580                         ldesc->flags |= PRL_LATCHED;
11581                 }
11582                 if (ldesc->flags & PRL_SUPPRESS)
11583                         suppress++;
11584         }
11585         if ((ptr->flags & PR_PREEN_NOMSG) &&
11586             (ctx->options & E2F_OPT_PREEN))
11587                 suppress++;
11588         if ((ptr->flags & PR_NO_NOMSG) &&
11589             (ctx->options & E2F_OPT_NO))
11590                 suppress++;
11591         if (!suppress) {
11592                 message = ptr->e2p_description;
11593                 if ((ctx->options & E2F_OPT_PREEN) &&
11594                     !(ptr->flags & PR_PREEN_NOHDR)) {
11595                         printf("%s: ", ctx->device_name ?
11596                                ctx->device_name : ctx->filesystem_name);
11597                 }
11598                 if (*message)
11599                         print_e2fsck_message(ctx, _(message), pctx, 1);
11600         }
11601         if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
11602                 preenhalt(ctx);
11603
11604         if (ptr->flags & PR_FATAL)
11605                 fatal_error(ctx, 0);
11606
11607         if (ptr->prompt == PROMPT_NONE) {
11608                 if (ptr->flags & PR_NOCOLLATE)
11609                         answer = -1;
11610                 else
11611                         answer = def_yn;
11612         } else {
11613                 if (ctx->options & E2F_OPT_PREEN) {
11614                         answer = def_yn;
11615                         if (!(ptr->flags & PR_PREEN_NOMSG))
11616                                 print_answer = 1;
11617                 } else if ((ptr->flags & PR_LATCH_MASK) &&
11618                            (ldesc->flags & (PRL_YES | PRL_NO))) {
11619                         if (!suppress)
11620                                 print_answer = 1;
11621                         if (ldesc->flags & PRL_YES)
11622                                 answer = 1;
11623                         else
11624                                 answer = 0;
11625                 } else
11626                         answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
11627                 if (!answer && !(ptr->flags & PR_NO_OK))
11628                         ext2fs_unmark_valid(fs);
11629
11630                 if (print_answer)
11631                         printf("%s.\n", answer ?
11632                                _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
11633
11634         }
11635
11636         if ((ptr->prompt == PROMPT_ABORT) && answer)
11637                 fatal_error(ctx, 0);
11638
11639         if (ptr->flags & PR_AFTER_CODE)
11640                 answer = fix_problem(ctx, ptr->second_code, pctx);
11641
11642         return answer;
11643 }
11644
11645 /*
11646  * linux/fs/recovery.c
11647  *
11648  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
11649  */
11650
11651 /*
11652  * Maintain information about the progress of the recovery job, so that
11653  * the different passes can carry information between them.
11654  */
11655 struct recovery_info
11656 {
11657         tid_t           start_transaction;
11658         tid_t           end_transaction;
11659
11660         int             nr_replays;
11661         int             nr_revokes;
11662         int             nr_revoke_hits;
11663 };
11664
11665 enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
11666 static int do_one_pass(journal_t *journal,
11667                                 struct recovery_info *info, enum passtype pass);
11668 static int scan_revoke_records(journal_t *, struct buffer_head *,
11669                                 tid_t, struct recovery_info *);
11670
11671 /*
11672  * Read a block from the journal
11673  */
11674
11675 static int jread(struct buffer_head **bhp, journal_t *journal,
11676                  unsigned int offset)
11677 {
11678         int err;
11679         unsigned long blocknr;
11680         struct buffer_head *bh;
11681
11682         *bhp = NULL;
11683
11684         J_ASSERT (offset < journal->j_maxlen);
11685
11686         err = journal_bmap(journal, offset, &blocknr);
11687
11688         if (err) {
11689                 printk (KERN_ERR "JBD: bad block at offset %u\n",
11690                         offset);
11691                 return err;
11692         }
11693
11694         bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
11695         if (!bh)
11696                 return -ENOMEM;
11697
11698         if (!buffer_uptodate(bh)) {
11699                 /* If this is a brand new buffer, start readahead.
11700                    Otherwise, we assume we are already reading it.  */
11701                 if (!buffer_req(bh))
11702                         do_readahead(journal, offset);
11703                 wait_on_buffer(bh);
11704         }
11705
11706         if (!buffer_uptodate(bh)) {
11707                 printk (KERN_ERR "JBD: Failed to read block at offset %u\n",
11708                         offset);
11709                 brelse(bh);
11710                 return -EIO;
11711         }
11712
11713         *bhp = bh;
11714         return 0;
11715 }
11716
11717
11718 /*
11719  * Count the number of in-use tags in a journal descriptor block.
11720  */
11721
11722 static int count_tags(struct buffer_head *bh, int size)
11723 {
11724         char *                  tagp;
11725         journal_block_tag_t *   tag;
11726         int                     nr = 0;
11727
11728         tagp = &bh->b_data[sizeof(journal_header_t)];
11729
11730         while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
11731                 tag = (journal_block_tag_t *) tagp;
11732
11733                 nr++;
11734                 tagp += sizeof(journal_block_tag_t);
11735                 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
11736                         tagp += 16;
11737
11738                 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
11739                         break;
11740         }
11741
11742         return nr;
11743 }
11744
11745
11746 /* Make sure we wrap around the log correctly! */
11747 #define wrap(journal, var)                                            \
11748 do {                                                                \
11749         if (var >= (journal)->j_last)                                   \
11750                 var -= ((journal)->j_last - (journal)->j_first);        \
11751 } while (0)
11752
11753 /**
11754  * int journal_recover(journal_t *journal) - recovers a on-disk journal
11755  * @journal: the journal to recover
11756  *
11757  * The primary function for recovering the log contents when mounting a
11758  * journaled device.
11759  *
11760  * Recovery is done in three passes.  In the first pass, we look for the
11761  * end of the log.  In the second, we assemble the list of revoke
11762  * blocks.  In the third and final pass, we replay any un-revoked blocks
11763  * in the log.
11764  */
11765 int journal_recover(journal_t *journal)
11766 {
11767         int                     err;
11768         journal_superblock_t *  sb;
11769
11770         struct recovery_info    info;
11771
11772         memset(&info, 0, sizeof(info));
11773         sb = journal->j_superblock;
11774
11775         /*
11776          * The journal superblock's s_start field (the current log head)
11777          * is always zero if, and only if, the journal was cleanly
11778          * unmounted.
11779          */
11780
11781         if (!sb->s_start) {
11782                 jbd_debug(1, "No recovery required, last transaction %d\n",
11783                           ntohl(sb->s_sequence));
11784                 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
11785                 return 0;
11786         }
11787
11788         err = do_one_pass(journal, &info, PASS_SCAN);
11789         if (!err)
11790                 err = do_one_pass(journal, &info, PASS_REVOKE);
11791         if (!err)
11792                 err = do_one_pass(journal, &info, PASS_REPLAY);
11793
11794         jbd_debug(0, "JBD: recovery, exit status %d, "
11795                   "recovered transactions %u to %u\n",
11796                   err, info.start_transaction, info.end_transaction);
11797         jbd_debug(0, "JBD: Replayed %d and revoked %d/%d blocks\n",
11798                   info.nr_replays, info.nr_revoke_hits, info.nr_revokes);
11799
11800         /* Restart the log at the next transaction ID, thus invalidating
11801          * any existing commit records in the log. */
11802         journal->j_transaction_sequence = ++info.end_transaction;
11803
11804         journal_clear_revoke(journal);
11805         sync_blockdev(journal->j_fs_dev);
11806         return err;
11807 }
11808
11809 static int do_one_pass(journal_t *journal,
11810                         struct recovery_info *info, enum passtype pass)
11811 {
11812         unsigned int            first_commit_ID, next_commit_ID;
11813         unsigned long           next_log_block;
11814         int                     err, success = 0;
11815         journal_superblock_t *  sb;
11816         journal_header_t *      tmp;
11817         struct buffer_head *    bh;
11818         unsigned int            sequence;
11819         int                     blocktype;
11820
11821         /* Precompute the maximum metadata descriptors in a descriptor block */
11822         int                     MAX_BLOCKS_PER_DESC;
11823         MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
11824                                / sizeof(journal_block_tag_t));
11825
11826         /*
11827          * First thing is to establish what we expect to find in the log
11828          * (in terms of transaction IDs), and where (in terms of log
11829          * block offsets): query the superblock.
11830          */
11831
11832         sb = journal->j_superblock;
11833         next_commit_ID = ntohl(sb->s_sequence);
11834         next_log_block = ntohl(sb->s_start);
11835
11836         first_commit_ID = next_commit_ID;
11837         if (pass == PASS_SCAN)
11838                 info->start_transaction = first_commit_ID;
11839
11840         jbd_debug(1, "Starting recovery pass %d\n", pass);
11841
11842         /*
11843          * Now we walk through the log, transaction by transaction,
11844          * making sure that each transaction has a commit block in the
11845          * expected place.  Each complete transaction gets replayed back
11846          * into the main filesystem.
11847          */
11848
11849         while (1) {
11850                 int                     flags;
11851                 char *                  tagp;
11852                 journal_block_tag_t *   tag;
11853                 struct buffer_head *    obh;
11854                 struct buffer_head *    nbh;
11855
11856                 /* If we already know where to stop the log traversal,
11857                  * check right now that we haven't gone past the end of
11858                  * the log. */
11859
11860                 if (pass != PASS_SCAN)
11861                         if (tid_geq(next_commit_ID, info->end_transaction))
11862                                 break;
11863
11864                 jbd_debug(2, "Scanning for sequence ID %u at %lu/%lu\n",
11865                           next_commit_ID, next_log_block, journal->j_last);
11866
11867                 /* Skip over each chunk of the transaction looking
11868                  * either the next descriptor block or the final commit
11869                  * record. */
11870
11871                 jbd_debug(3, "JBD: checking block %ld\n", next_log_block);
11872                 err = jread(&bh, journal, next_log_block);
11873                 if (err)
11874                         goto failed;
11875
11876                 next_log_block++;
11877                 wrap(journal, next_log_block);
11878
11879                 /* What kind of buffer is it?
11880                  *
11881                  * If it is a descriptor block, check that it has the
11882                  * expected sequence number.  Otherwise, we're all done
11883                  * here. */
11884
11885                 tmp = (journal_header_t *)bh->b_data;
11886
11887                 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
11888                         brelse(bh);
11889                         break;
11890                 }
11891
11892                 blocktype = ntohl(tmp->h_blocktype);
11893                 sequence = ntohl(tmp->h_sequence);
11894                 jbd_debug(3, "Found magic %d, sequence %d\n",
11895                           blocktype, sequence);
11896
11897                 if (sequence != next_commit_ID) {
11898                         brelse(bh);
11899                         break;
11900                 }
11901
11902                 /* OK, we have a valid descriptor block which matches
11903                  * all of the sequence number checks.  What are we going
11904                  * to do with it?  That depends on the pass... */
11905
11906                 switch(blocktype) {
11907                 case JFS_DESCRIPTOR_BLOCK:
11908                         /* If it is a valid descriptor block, replay it
11909                          * in pass REPLAY; otherwise, just skip over the
11910                          * blocks it describes. */
11911                         if (pass != PASS_REPLAY) {
11912                                 next_log_block +=
11913                                         count_tags(bh, journal->j_blocksize);
11914                                 wrap(journal, next_log_block);
11915                                 brelse(bh);
11916                                 continue;
11917                         }
11918
11919                         /* A descriptor block: we can now write all of
11920                          * the data blocks.  Yay, useful work is finally
11921                          * getting done here! */
11922
11923                         tagp = &bh->b_data[sizeof(journal_header_t)];
11924                         while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
11925                                <= journal->j_blocksize) {
11926                                 unsigned long io_block;
11927
11928                                 tag = (journal_block_tag_t *) tagp;
11929                                 flags = ntohl(tag->t_flags);
11930
11931                                 io_block = next_log_block++;
11932                                 wrap(journal, next_log_block);
11933                                 err = jread(&obh, journal, io_block);
11934                                 if (err) {
11935                                         /* Recover what we can, but
11936                                          * report failure at the end. */
11937                                         success = err;
11938                                         printk (KERN_ERR
11939                                                 "JBD: IO error %d recovering "
11940                                                 "block %ld in log\n",
11941                                                 err, io_block);
11942                                 } else {
11943                                         unsigned long blocknr;
11944
11945                                         J_ASSERT(obh != NULL);
11946                                         blocknr = ntohl(tag->t_blocknr);
11947
11948                                         /* If the block has been
11949                                          * revoked, then we're all done
11950                                          * here. */
11951                                         if (journal_test_revoke
11952                                             (journal, blocknr,
11953                                              next_commit_ID)) {
11954                                                 brelse(obh);
11955                                                 ++info->nr_revoke_hits;
11956                                                 goto skip_write;
11957                                         }
11958
11959                                         /* Find a buffer for the new
11960                                          * data being restored */
11961                                         nbh = getblk(journal->j_fs_dev,
11962                                                        blocknr,
11963                                                      journal->j_blocksize);
11964                                         if (nbh == NULL) {
11965                                                 printk(KERN_ERR
11966                                                        "JBD: Out of memory "
11967                                                        "during recovery.\n");
11968                                                 err = -ENOMEM;
11969                                                 brelse(bh);
11970                                                 brelse(obh);
11971                                                 goto failed;
11972                                         }
11973
11974                                         lock_buffer(nbh);
11975                                         memcpy(nbh->b_data, obh->b_data,
11976                                                         journal->j_blocksize);
11977                                         if (flags & JFS_FLAG_ESCAPE) {
11978                                                 *((unsigned int *)bh->b_data) =
11979                                                         htonl(JFS_MAGIC_NUMBER);
11980                                         }
11981
11982                                         BUFFER_TRACE(nbh, "marking dirty");
11983                                         mark_buffer_uptodate(nbh, 1);
11984                                         mark_buffer_dirty(nbh);
11985                                         BUFFER_TRACE(nbh, "marking uptodate");
11986                                         ++info->nr_replays;
11987                                         /* ll_rw_block(WRITE, 1, &nbh); */
11988                                         unlock_buffer(nbh);
11989                                         brelse(obh);
11990                                         brelse(nbh);
11991                                 }
11992
11993                         skip_write:
11994                                 tagp += sizeof(journal_block_tag_t);
11995                                 if (!(flags & JFS_FLAG_SAME_UUID))
11996                                         tagp += 16;
11997
11998                                 if (flags & JFS_FLAG_LAST_TAG)
11999                                         break;
12000                         }
12001
12002                         brelse(bh);
12003                         continue;
12004
12005                 case JFS_COMMIT_BLOCK:
12006                         /* Found an expected commit block: not much to
12007                          * do other than move on to the next sequence
12008                          * number. */
12009                         brelse(bh);
12010                         next_commit_ID++;
12011                         continue;
12012
12013                 case JFS_REVOKE_BLOCK:
12014                         /* If we aren't in the REVOKE pass, then we can
12015                          * just skip over this block. */
12016                         if (pass != PASS_REVOKE) {
12017                                 brelse(bh);
12018                                 continue;
12019                         }
12020
12021                         err = scan_revoke_records(journal, bh,
12022                                                   next_commit_ID, info);
12023                         brelse(bh);
12024                         if (err)
12025                                 goto failed;
12026                         continue;
12027
12028                 default:
12029                         jbd_debug(3, "Unrecognised magic %d, end of scan.\n",
12030                                   blocktype);
12031                         goto done;
12032                 }
12033         }
12034
12035  done:
12036         /*
12037          * We broke out of the log scan loop: either we came to the
12038          * known end of the log or we found an unexpected block in the
12039          * log.  If the latter happened, then we know that the "current"
12040          * transaction marks the end of the valid log.
12041          */
12042
12043         if (pass == PASS_SCAN)
12044                 info->end_transaction = next_commit_ID;
12045         else {
12046                 /* It's really bad news if different passes end up at
12047                  * different places (but possible due to IO errors). */
12048                 if (info->end_transaction != next_commit_ID) {
12049                         printk (KERN_ERR "JBD: recovery pass %d ended at "
12050                                 "transaction %u, expected %u\n",
12051                                 pass, next_commit_ID, info->end_transaction);
12052                         if (!success)
12053                                 success = -EIO;
12054                 }
12055         }
12056
12057         return success;
12058
12059  failed:
12060         return err;
12061 }
12062
12063
12064 /* Scan a revoke record, marking all blocks mentioned as revoked. */
12065
12066 static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
12067                                tid_t sequence, struct recovery_info *info)
12068 {
12069         journal_revoke_header_t *header;
12070         int offset, max;
12071
12072         header = (journal_revoke_header_t *) bh->b_data;
12073         offset = sizeof(journal_revoke_header_t);
12074         max = ntohl(header->r_count);
12075
12076         while (offset < max) {
12077                 unsigned long blocknr;
12078                 int err;
12079
12080                 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
12081                 offset += 4;
12082                 err = journal_set_revoke(journal, blocknr, sequence);
12083                 if (err)
12084                         return err;
12085                 ++info->nr_revokes;
12086         }
12087         return 0;
12088 }
12089
12090
12091 /*
12092  * rehash.c --- rebuild hash tree directories
12093  *
12094  * This algorithm is designed for simplicity of implementation and to
12095  * pack the directory as much as possible.  It however requires twice
12096  * as much memory as the size of the directory.  The maximum size
12097  * directory supported using a 4k blocksize is roughly a gigabyte, and
12098  * so there may very well be problems with machines that don't have
12099  * virtual memory, and obscenely large directories.
12100  *
12101  * An alternate algorithm which is much more disk intensive could be
12102  * written, and probably will need to be written in the future.  The
12103  * design goals of such an algorithm are: (a) use (roughly) constant
12104  * amounts of memory, no matter how large the directory, (b) the
12105  * directory must be safe at all times, even if e2fsck is interrupted
12106  * in the middle, (c) we must use minimal amounts of extra disk
12107  * blocks.  This pretty much requires an incremental approach, where
12108  * we are reading from one part of the directory, and inserting into
12109  * the front half.  So the algorithm will have to keep track of a
12110  * moving block boundary between the new tree and the old tree, and
12111  * files will need to be moved from the old directory and inserted
12112  * into the new tree.  If the new directory requires space which isn't
12113  * yet available, blocks from the beginning part of the old directory
12114  * may need to be moved to the end of the directory to make room for
12115  * the new tree:
12116  *
12117  *    --------------------------------------------------------
12118  *    |  new tree   |        | old tree                      |
12119  *    --------------------------------------------------------
12120  *                  ^ ptr    ^ptr
12121  *                tail new   head old
12122  *
12123  * This is going to be a pain in the tuckus to implement, and will
12124  * require a lot more disk accesses.  So I'm going to skip it for now;
12125  * it's only really going to be an issue for really, really big
12126  * filesystems (when we reach the level of tens of millions of files
12127  * in a single directory).  It will probably be easier to simply
12128  * require that e2fsck use VM first.
12129  */
12130
12131 struct fill_dir_struct {
12132         char *buf;
12133         struct ext2_inode *inode;
12134         int err;
12135         e2fsck_t ctx;
12136         struct hash_entry *harray;
12137         int max_array, num_array;
12138         int dir_size;
12139         int compress;
12140         ino_t parent;
12141 };
12142
12143 struct hash_entry {
12144         ext2_dirhash_t  hash;
12145         ext2_dirhash_t  minor_hash;
12146         struct ext2_dir_entry   *dir;
12147 };
12148
12149 struct out_dir {
12150         int             num;
12151         int             max;
12152         char            *buf;
12153         ext2_dirhash_t  *hashes;
12154 };
12155
12156 static int fill_dir_block(ext2_filsys fs,
12157                           blk_t *block_nr,
12158                           e2_blkcnt_t blockcnt,
12159                           blk_t ref_block FSCK_ATTR((unused)),
12160                           int ref_offset FSCK_ATTR((unused)),
12161                           void *priv_data)
12162 {
12163         struct fill_dir_struct  *fd = (struct fill_dir_struct *) priv_data;
12164         struct hash_entry       *new_array, *ent;
12165         struct ext2_dir_entry   *dirent;
12166         char                    *dir;
12167         unsigned int            offset, dir_offset;
12168
12169         if (blockcnt < 0)
12170                 return 0;
12171
12172         offset = blockcnt * fs->blocksize;
12173         if (offset + fs->blocksize > fd->inode->i_size) {
12174                 fd->err = EXT2_ET_DIR_CORRUPTED;
12175                 return BLOCK_ABORT;
12176         }
12177         dir = (fd->buf+offset);
12178         if (HOLE_BLKADDR(*block_nr)) {
12179                 memset(dir, 0, fs->blocksize);
12180                 dirent = (struct ext2_dir_entry *) dir;
12181                 dirent->rec_len = fs->blocksize;
12182         } else {
12183                 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
12184                 if (fd->err)
12185                         return BLOCK_ABORT;
12186         }
12187         /* While the directory block is "hot", index it. */
12188         dir_offset = 0;
12189         while (dir_offset < fs->blocksize) {
12190                 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
12191                 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
12192                     (dirent->rec_len < 8) ||
12193                     ((dirent->rec_len % 4) != 0) ||
12194                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
12195                         fd->err = EXT2_ET_DIR_CORRUPTED;
12196                         return BLOCK_ABORT;
12197                 }
12198                 dir_offset += dirent->rec_len;
12199                 if (dirent->inode == 0)
12200                         continue;
12201                 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
12202                     (dirent->name[0] == '.'))
12203                         continue;
12204                 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
12205                     (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
12206                         fd->parent = dirent->inode;
12207                         continue;
12208                 }
12209                 if (fd->num_array >= fd->max_array) {
12210                         new_array = realloc(fd->harray,
12211                             sizeof(struct hash_entry) * (fd->max_array+500));
12212                         if (!new_array) {
12213                                 fd->err = ENOMEM;
12214                                 return BLOCK_ABORT;
12215                         }
12216                         fd->harray = new_array;
12217                         fd->max_array += 500;
12218                 }
12219                 ent = fd->harray + fd->num_array++;
12220                 ent->dir = dirent;
12221                 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
12222                 if (fd->compress)
12223                         ent->hash = ent->minor_hash = 0;
12224                 else {
12225                         fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
12226                                                  dirent->name,
12227                                                  dirent->name_len & 0xFF,
12228                                                  fs->super->s_hash_seed,
12229                                                  &ent->hash, &ent->minor_hash);
12230                         if (fd->err)
12231                                 return BLOCK_ABORT;
12232                 }
12233         }
12234
12235         return 0;
12236 }
12237
12238 /* Used for sorting the hash entry */
12239 static EXT2_QSORT_TYPE name_cmp(const void *a, const void *b)
12240 {
12241         const struct hash_entry *he_a = (const struct hash_entry *) a;
12242         const struct hash_entry *he_b = (const struct hash_entry *) b;
12243         int     ret;
12244         int     min_len;
12245
12246         min_len = he_a->dir->name_len;
12247         if (min_len > he_b->dir->name_len)
12248                 min_len = he_b->dir->name_len;
12249
12250         ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
12251         if (ret == 0) {
12252                 if (he_a->dir->name_len > he_b->dir->name_len)
12253                         ret = 1;
12254                 else if (he_a->dir->name_len < he_b->dir->name_len)
12255                         ret = -1;
12256                 else
12257                         ret = he_b->dir->inode - he_a->dir->inode;
12258         }
12259         return ret;
12260 }
12261
12262 /* Used for sorting the hash entry */
12263 static EXT2_QSORT_TYPE hash_cmp(const void *a, const void *b)
12264 {
12265         const struct hash_entry *he_a = (const struct hash_entry *) a;
12266         const struct hash_entry *he_b = (const struct hash_entry *) b;
12267         int     ret;
12268
12269         if (he_a->hash > he_b->hash)
12270                 ret = 1;
12271         else if (he_a->hash < he_b->hash)
12272                 ret = -1;
12273         else {
12274                 if (he_a->minor_hash > he_b->minor_hash)
12275                         ret = 1;
12276                 else if (he_a->minor_hash < he_b->minor_hash)
12277                         ret = -1;
12278                 else
12279                         ret = name_cmp(a, b);
12280         }
12281         return ret;
12282 }
12283
12284 static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
12285                                 int blocks)
12286 {
12287         void                    *new_mem;
12288
12289         if (outdir->max) {
12290                 new_mem = realloc(outdir->buf, blocks * fs->blocksize);
12291                 if (!new_mem)
12292                         return ENOMEM;
12293                 outdir->buf = new_mem;
12294                 new_mem = realloc(outdir->hashes,
12295                                   blocks * sizeof(ext2_dirhash_t));
12296                 if (!new_mem)
12297                         return ENOMEM;
12298                 outdir->hashes = new_mem;
12299         } else {
12300                 outdir->buf = malloc(blocks * fs->blocksize);
12301                 outdir->hashes = malloc(blocks * sizeof(ext2_dirhash_t));
12302                 outdir->num = 0;
12303         }
12304         outdir->max = blocks;
12305         return 0;
12306 }
12307
12308 static void free_out_dir(struct out_dir *outdir)
12309 {
12310         free(outdir->buf);
12311         free(outdir->hashes);
12312         outdir->max = 0;
12313         outdir->num =0;
12314 }
12315
12316 static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
12317                          char ** ret)
12318 {
12319         errcode_t       retval;
12320
12321         if (outdir->num >= outdir->max) {
12322                 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
12323                 if (retval)
12324                         return retval;
12325         }
12326         *ret = outdir->buf + (outdir->num++ * fs->blocksize);
12327         memset(*ret, 0, fs->blocksize);
12328         return 0;
12329 }
12330
12331 /*
12332  * This function is used to make a unique filename.  We do this by
12333  * appending ~0, and then incrementing the number.  However, we cannot
12334  * expand the length of the filename beyond the padding available in
12335  * the directory entry.
12336  */
12337 static void mutate_name(char *str, __u16 *len)
12338 {
12339         int     i;
12340         __u16   l = *len & 0xFF, h = *len & 0xff00;
12341
12342         /*
12343          * First check to see if it looks the name has been mutated
12344          * already
12345          */
12346         for (i = l-1; i > 0; i--) {
12347                 if (!isdigit(str[i]))
12348                         break;
12349         }
12350         if ((i == l-1) || (str[i] != '~')) {
12351                 if (((l-1) & 3) < 2)
12352                         l += 2;
12353                 else
12354                         l = (l+3) & ~3;
12355                 str[l-2] = '~';
12356                 str[l-1] = '0';
12357                 *len = l | h;
12358                 return;
12359         }
12360         for (i = l-1; i >= 0; i--) {
12361                 if (isdigit(str[i])) {
12362                         if (str[i] == '9')
12363                                 str[i] = '0';
12364                         else {
12365                                 str[i]++;
12366                                 return;
12367                         }
12368                         continue;
12369                 }
12370                 if (i == 1) {
12371                         if (str[0] == 'z')
12372                                 str[0] = 'A';
12373                         else if (str[0] == 'Z') {
12374                                 str[0] = '~';
12375                                 str[1] = '0';
12376                         } else
12377                                 str[0]++;
12378                 } else if (i > 0) {
12379                         str[i] = '1';
12380                         str[i-1] = '~';
12381                 } else {
12382                         if (str[0] == '~')
12383                                 str[0] = 'a';
12384                         else
12385                                 str[0]++;
12386                 }
12387                 break;
12388         }
12389 }
12390
12391 static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
12392                                     ext2_ino_t ino,
12393                                     struct fill_dir_struct *fd)
12394 {
12395         struct problem_context  pctx;
12396         struct hash_entry       *ent, *prev;
12397         int                     i, j;
12398         int                     fixed = 0;
12399         char                    new_name[256];
12400         __u16                   new_len;
12401
12402         clear_problem_context(&pctx);
12403         pctx.ino = ino;
12404
12405         for (i=1; i < fd->num_array; i++) {
12406                 ent = fd->harray + i;
12407                 prev = ent - 1;
12408                 if (!ent->dir->inode ||
12409                     ((ent->dir->name_len & 0xFF) !=
12410                      (prev->dir->name_len & 0xFF)) ||
12411                     (strncmp(ent->dir->name, prev->dir->name,
12412                              ent->dir->name_len & 0xFF)))
12413                         continue;
12414                 pctx.dirent = ent->dir;
12415                 if ((ent->dir->inode == prev->dir->inode) &&
12416                     fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
12417                         e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
12418                         ent->dir->inode = 0;
12419                         fixed++;
12420                         continue;
12421                 }
12422                 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
12423                 new_len = ent->dir->name_len;
12424                 mutate_name(new_name, &new_len);
12425                 for (j=0; j < fd->num_array; j++) {
12426                         if ((i==j) ||
12427                             ((ent->dir->name_len & 0xFF) !=
12428                              (fd->harray[j].dir->name_len & 0xFF)) ||
12429                             (strncmp(new_name, fd->harray[j].dir->name,
12430                                      new_len & 0xFF)))
12431                                 continue;
12432                         mutate_name(new_name, &new_len);
12433
12434                         j = -1;
12435                 }
12436                 new_name[new_len & 0xFF] = 0;
12437                 pctx.str = new_name;
12438                 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
12439                         memcpy(ent->dir->name, new_name, new_len & 0xFF);
12440                         ent->dir->name_len = new_len;
12441                         ext2fs_dirhash(fs->super->s_def_hash_version,
12442                                        ent->dir->name,
12443                                        ent->dir->name_len & 0xFF,
12444                                        fs->super->s_hash_seed,
12445                                        &ent->hash, &ent->minor_hash);
12446                         fixed++;
12447                 }
12448         }
12449         return fixed;
12450 }
12451
12452
12453 static errcode_t copy_dir_entries(ext2_filsys fs,
12454                                   struct fill_dir_struct *fd,
12455                                   struct out_dir *outdir)
12456 {
12457         errcode_t               retval;
12458         char                    *block_start;
12459         struct hash_entry       *ent;
12460         struct ext2_dir_entry   *dirent;
12461         int                     i, rec_len, left;
12462         ext2_dirhash_t          prev_hash;
12463         int                     offset;
12464
12465         outdir->max = 0;
12466         retval = alloc_size_dir(fs, outdir,
12467                                 (fd->dir_size / fs->blocksize) + 2);
12468         if (retval)
12469                 return retval;
12470         outdir->num = fd->compress ? 0 : 1;
12471         offset = 0;
12472         outdir->hashes[0] = 0;
12473         prev_hash = 1;
12474         if ((retval = get_next_block(fs, outdir, &block_start)))
12475                 return retval;
12476         dirent = (struct ext2_dir_entry *) block_start;
12477         left = fs->blocksize;
12478         for (i=0; i < fd->num_array; i++) {
12479                 ent = fd->harray + i;
12480                 if (ent->dir->inode == 0)
12481                         continue;
12482                 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
12483                 if (rec_len > left) {
12484                         if (left)
12485                                 dirent->rec_len += left;
12486                         if ((retval = get_next_block(fs, outdir,
12487                                                       &block_start)))
12488                                 return retval;
12489                         offset = 0;
12490                 }
12491                 left = fs->blocksize - offset;
12492                 dirent = (struct ext2_dir_entry *) (block_start + offset);
12493                 if (offset == 0) {
12494                         if (ent->hash == prev_hash)
12495                                 outdir->hashes[outdir->num-1] = ent->hash | 1;
12496                         else
12497                                 outdir->hashes[outdir->num-1] = ent->hash;
12498                 }
12499                 dirent->inode = ent->dir->inode;
12500                 dirent->name_len = ent->dir->name_len;
12501                 dirent->rec_len = rec_len;
12502                 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
12503                 offset += rec_len;
12504                 left -= rec_len;
12505                 if (left < 12) {
12506                         dirent->rec_len += left;
12507                         offset += left;
12508                         left = 0;
12509                 }
12510                 prev_hash = ent->hash;
12511         }
12512         if (left)
12513                 dirent->rec_len += left;
12514
12515         return 0;
12516 }
12517
12518
12519 static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
12520                                     ext2_ino_t ino, ext2_ino_t parent)
12521 {
12522         struct ext2_dir_entry           *dir;
12523         struct ext2_dx_root_info        *root;
12524         struct ext2_dx_countlimit       *limits;
12525         int                             filetype = 0;
12526
12527         if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
12528                 filetype = EXT2_FT_DIR << 8;
12529
12530         memset(buf, 0, fs->blocksize);
12531         dir = (struct ext2_dir_entry *) buf;
12532         dir->inode = ino;
12533         dir->name[0] = '.';
12534         dir->name_len = 1 | filetype;
12535         dir->rec_len = 12;
12536         dir = (struct ext2_dir_entry *) (buf + 12);
12537         dir->inode = parent;
12538         dir->name[0] = '.';
12539         dir->name[1] = '.';
12540         dir->name_len = 2 | filetype;
12541         dir->rec_len = fs->blocksize - 12;
12542
12543         root = (struct ext2_dx_root_info *) (buf+24);
12544         root->reserved_zero = 0;
12545         root->hash_version = fs->super->s_def_hash_version;
12546         root->info_length = 8;
12547         root->indirect_levels = 0;
12548         root->unused_flags = 0;
12549
12550         limits = (struct ext2_dx_countlimit *) (buf+32);
12551         limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
12552         limits->count = 0;
12553
12554         return root;
12555 }
12556
12557
12558 static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
12559 {
12560         struct ext2_dir_entry           *dir;
12561         struct ext2_dx_countlimit       *limits;
12562
12563         memset(buf, 0, fs->blocksize);
12564         dir = (struct ext2_dir_entry *) buf;
12565         dir->inode = 0;
12566         dir->rec_len = fs->blocksize;
12567
12568         limits = (struct ext2_dx_countlimit *) (buf+8);
12569         limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
12570         limits->count = 0;
12571
12572         return (struct ext2_dx_entry *) limits;
12573 }
12574
12575 /*
12576  * This function takes the leaf nodes which have been written in
12577  * outdir, and populates the root node and any necessary interior nodes.
12578  */
12579 static errcode_t calculate_tree(ext2_filsys fs,
12580                                 struct out_dir *outdir,
12581                                 ext2_ino_t ino,
12582                                 ext2_ino_t parent)
12583 {
12584         struct ext2_dx_root_info        *root_info;
12585         struct ext2_dx_entry            *root, *dx_ent = 0;
12586         struct ext2_dx_countlimit       *root_limit, *limit;
12587         errcode_t                       retval;
12588         char                            * block_start;
12589         int                             i, c1, c2, nblks;
12590         int                             limit_offset, root_offset;
12591
12592         root_info = set_root_node(fs, outdir->buf, ino, parent);
12593         root_offset = limit_offset = ((char *) root_info - outdir->buf) +
12594                 root_info->info_length;
12595         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
12596         c1 = root_limit->limit;
12597         nblks = outdir->num;
12598
12599         /* Write out the pointer blocks */
12600         if (nblks-1 <= c1) {
12601                 /* Just write out the root block, and we're done */
12602                 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
12603                 for (i=1; i < nblks; i++) {
12604                         root->block = ext2fs_cpu_to_le32(i);
12605                         if (i != 1)
12606                                 root->hash =
12607                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
12608                         root++;
12609                         c1--;
12610                 }
12611         } else {
12612                 c2 = 0;
12613                 limit = 0;
12614                 root_info->indirect_levels = 1;
12615                 for (i=1; i < nblks; i++) {
12616                         if (c1 == 0)
12617                                 return ENOSPC;
12618                         if (c2 == 0) {
12619                                 if (limit)
12620                                         limit->limit = limit->count =
12621                 ext2fs_cpu_to_le16(limit->limit);
12622                                 root = (struct ext2_dx_entry *)
12623                                         (outdir->buf + root_offset);
12624                                 root->block = ext2fs_cpu_to_le32(outdir->num);
12625                                 if (i != 1)
12626                                         root->hash =
12627                         ext2fs_cpu_to_le32(outdir->hashes[i]);
12628                                 if ((retval =  get_next_block(fs, outdir,
12629                                                               &block_start)))
12630                                         return retval;
12631                                 dx_ent = set_int_node(fs, block_start);
12632                                 limit = (struct ext2_dx_countlimit *) dx_ent;
12633                                 c2 = limit->limit;
12634                                 root_offset += sizeof(struct ext2_dx_entry);
12635                                 c1--;
12636                         }
12637                         dx_ent->block = ext2fs_cpu_to_le32(i);
12638                         if (c2 != limit->limit)
12639                                 dx_ent->hash =
12640                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
12641                         dx_ent++;
12642                         c2--;
12643                 }
12644                 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
12645                 limit->limit = ext2fs_cpu_to_le16(limit->limit);
12646         }
12647         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
12648         root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
12649         root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
12650
12651         return 0;
12652 }
12653
12654 struct write_dir_struct {
12655         struct out_dir *outdir;
12656         errcode_t       err;
12657         e2fsck_t        ctx;
12658         int             cleared;
12659 };
12660
12661 /*
12662  * Helper function which writes out a directory block.
12663  */
12664 static int write_dir_block(ext2_filsys fs,
12665                            blk_t        *block_nr,
12666                            e2_blkcnt_t blockcnt,
12667                            blk_t ref_block FSCK_ATTR((unused)),
12668                            int ref_offset FSCK_ATTR((unused)),
12669                            void *priv_data)
12670 {
12671         struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
12672         blk_t   blk;
12673         char    *dir;
12674
12675         if (*block_nr == 0)
12676                 return 0;
12677         if (blockcnt >= wd->outdir->num) {
12678                 e2fsck_read_bitmaps(wd->ctx);
12679                 blk = *block_nr;
12680                 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
12681                 ext2fs_block_alloc_stats(fs, blk, -1);
12682                 *block_nr = 0;
12683                 wd->cleared++;
12684                 return BLOCK_CHANGED;
12685         }
12686         if (blockcnt < 0)
12687                 return 0;
12688
12689         dir = wd->outdir->buf + (blockcnt * fs->blocksize);
12690         wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
12691         if (wd->err)
12692                 return BLOCK_ABORT;
12693         return 0;
12694 }
12695
12696 static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
12697                                  struct out_dir *outdir,
12698                                  ext2_ino_t ino, int compress)
12699 {
12700         struct write_dir_struct wd;
12701         errcode_t       retval;
12702         struct ext2_inode       inode;
12703
12704         retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
12705         if (retval)
12706                 return retval;
12707
12708         wd.outdir = outdir;
12709         wd.err = 0;
12710         wd.ctx = ctx;
12711         wd.cleared = 0;
12712
12713         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
12714                                        write_dir_block, &wd);
12715         if (retval)
12716                 return retval;
12717         if (wd.err)
12718                 return wd.err;
12719
12720         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
12721         if (compress)
12722                 inode.i_flags &= ~EXT2_INDEX_FL;
12723         else
12724                 inode.i_flags |= EXT2_INDEX_FL;
12725         inode.i_size = outdir->num * fs->blocksize;
12726         inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
12727         e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
12728
12729         return 0;
12730 }
12731
12732 static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
12733 {
12734         ext2_filsys             fs = ctx->fs;
12735         errcode_t               retval;
12736         struct ext2_inode       inode;
12737         char                    *dir_buf = 0;
12738         struct fill_dir_struct  fd;
12739         struct out_dir          outdir;
12740
12741         outdir.max = outdir.num = 0;
12742         outdir.buf = 0;
12743         outdir.hashes = 0;
12744         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
12745
12746         retval = ENOMEM;
12747         fd.harray = 0;
12748         dir_buf = malloc(inode.i_size);
12749         if (!dir_buf)
12750                 goto errout;
12751
12752         fd.max_array = inode.i_size / 32;
12753         fd.num_array = 0;
12754         fd.harray = malloc(fd.max_array * sizeof(struct hash_entry));
12755         if (!fd.harray)
12756                 goto errout;
12757
12758         fd.ctx = ctx;
12759         fd.buf = dir_buf;
12760         fd.inode = &inode;
12761         fd.err = 0;
12762         fd.dir_size = 0;
12763         fd.compress = 0;
12764         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
12765             (inode.i_size / fs->blocksize) < 2)
12766                 fd.compress = 1;
12767         fd.parent = 0;
12768
12769         /* Read in the entire directory into memory */
12770         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
12771                                        fill_dir_block, &fd);
12772         if (fd.err) {
12773                 retval = fd.err;
12774                 goto errout;
12775         }
12776
12777 #if 0
12778         printf("%d entries (%d bytes) found in inode %d\n",
12779                fd.num_array, fd.dir_size, ino);
12780 #endif
12781
12782         /* Sort the list */
12783 resort:
12784         if (fd.compress)
12785                 qsort(fd.harray+2, fd.num_array-2,
12786                       sizeof(struct hash_entry), name_cmp);
12787         else
12788                 qsort(fd.harray, fd.num_array,
12789                       sizeof(struct hash_entry), hash_cmp);
12790
12791         /*
12792          * Look for duplicates
12793          */
12794         if (duplicate_search_and_fix(ctx, fs, ino, &fd))
12795                 goto resort;
12796
12797         if (ctx->options & E2F_OPT_NO) {
12798                 retval = 0;
12799                 goto errout;
12800         }
12801
12802         /*
12803          * Copy the directory entries.  In a htree directory these
12804          * will become the leaf nodes.
12805          */
12806         retval = copy_dir_entries(fs, &fd, &outdir);
12807         if (retval)
12808                 goto errout;
12809
12810         free(dir_buf); dir_buf = 0;
12811
12812         if (!fd.compress) {
12813                 /* Calculate the interior nodes */
12814                 retval = calculate_tree(fs, &outdir, ino, fd.parent);
12815                 if (retval)
12816                         goto errout;
12817         }
12818
12819         retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
12820
12821 errout:
12822         free(dir_buf);
12823         free(fd.harray);
12824
12825         free_out_dir(&outdir);
12826         return retval;
12827 }
12828
12829 void e2fsck_rehash_directories(e2fsck_t ctx)
12830 {
12831         struct problem_context  pctx;
12832 #ifdef RESOURCE_TRACK
12833         struct resource_track   rtrack;
12834 #endif
12835         struct dir_info         *dir;
12836         ext2_u32_iterate        iter;
12837         ext2_ino_t              ino;
12838         errcode_t               retval;
12839         int                     i, cur, max, all_dirs, dir_index, first = 1;
12840
12841 #ifdef RESOURCE_TRACK
12842         init_resource_track(&rtrack);
12843 #endif
12844
12845         all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
12846
12847         if (!ctx->dirs_to_hash && !all_dirs)
12848                 return;
12849
12850         e2fsck_get_lost_and_found(ctx, 0);
12851
12852         clear_problem_context(&pctx);
12853
12854         dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
12855         cur = 0;
12856         if (all_dirs) {
12857                 i = 0;
12858                 max = e2fsck_get_num_dirinfo(ctx);
12859         } else {
12860                 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
12861                                                        &iter);
12862                 if (retval) {
12863                         pctx.errcode = retval;
12864                         fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
12865                         return;
12866                 }
12867                 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
12868         }
12869         while (1) {
12870                 if (all_dirs) {
12871                         if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
12872                                 break;
12873                         ino = dir->ino;
12874                 } else {
12875                         if (!ext2fs_u32_list_iterate(iter, &ino))
12876                                 break;
12877                 }
12878                 if (ino == ctx->lost_and_found)
12879                         continue;
12880                 pctx.dir = ino;
12881                 if (first) {
12882                         fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
12883                         first = 0;
12884                 }
12885 #if 0
12886                 fix_problem(ctx, PR_3A_OPTIMIZE_DIR, &pctx);
12887 #endif
12888                 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
12889                 if (pctx.errcode) {
12890                         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
12891                         fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
12892                 }
12893                 if (ctx->progress && !ctx->progress_fd)
12894                         e2fsck_simple_progress(ctx, "Rebuilding directory",
12895                                100.0 * (float) (++cur) / (float) max, ino);
12896         }
12897         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
12898         if (!all_dirs)
12899                 ext2fs_u32_list_iterate_end(iter);
12900
12901         ext2fs_u32_list_free(ctx->dirs_to_hash);
12902         ctx->dirs_to_hash = 0;
12903
12904 #ifdef RESOURCE_TRACK
12905         if (ctx->options & E2F_OPT_TIME2) {
12906                 e2fsck_clear_progbar(ctx);
12907                 print_resource_track("Pass 3A", &rtrack);
12908         }
12909 #endif
12910 }
12911
12912 /*
12913  * linux/fs/revoke.c
12914  *
12915  * Journal revoke routines for the generic filesystem journaling code;
12916  * part of the ext2fs journaling system.
12917  *
12918  * Revoke is the mechanism used to prevent old log records for deleted
12919  * metadata from being replayed on top of newer data using the same
12920  * blocks.  The revoke mechanism is used in two separate places:
12921  *
12922  * + Commit: during commit we write the entire list of the current
12923  *   transaction's revoked blocks to the journal
12924  *
12925  * + Recovery: during recovery we record the transaction ID of all
12926  *   revoked blocks.  If there are multiple revoke records in the log
12927  *   for a single block, only the last one counts, and if there is a log
12928  *   entry for a block beyond the last revoke, then that log entry still
12929  *   gets replayed.
12930  *
12931  * We can get interactions between revokes and new log data within a
12932  * single transaction:
12933  *
12934  * Block is revoked and then journaled:
12935  *   The desired end result is the journaling of the new block, so we
12936  *   cancel the revoke before the transaction commits.
12937  *
12938  * Block is journaled and then revoked:
12939  *   The revoke must take precedence over the write of the block, so we
12940  *   need either to cancel the journal entry or to write the revoke
12941  *   later in the log than the log block.  In this case, we choose the
12942  *   latter: journaling a block cancels any revoke record for that block
12943  *   in the current transaction, so any revoke for that block in the
12944  *   transaction must have happened after the block was journaled and so
12945  *   the revoke must take precedence.
12946  *
12947  * Block is revoked and then written as data:
12948  *   The data write is allowed to succeed, but the revoke is _not_
12949  *   cancelled.  We still need to prevent old log records from
12950  *   overwriting the new data.  We don't even need to clear the revoke
12951  *   bit here.
12952  *
12953  * Revoke information on buffers is a tri-state value:
12954  *
12955  * RevokeValid clear:   no cached revoke status, need to look it up
12956  * RevokeValid set, Revoked clear:
12957  *                      buffer has not been revoked, and cancel_revoke
12958  *                      need do nothing.
12959  * RevokeValid set, Revoked set:
12960  *                      buffer has been revoked.
12961  */
12962
12963 static kmem_cache_t *revoke_record_cache;
12964 static kmem_cache_t *revoke_table_cache;
12965
12966 /* Each revoke record represents one single revoked block.  During
12967    journal replay, this involves recording the transaction ID of the
12968    last transaction to revoke this block. */
12969
12970 struct jbd_revoke_record_s
12971 {
12972         struct list_head  hash;
12973         tid_t             sequence;     /* Used for recovery only */
12974         unsigned long     blocknr;
12975 };
12976
12977
12978 /* The revoke table is just a simple hash table of revoke records. */
12979 struct jbd_revoke_table_s
12980 {
12981         /* It is conceivable that we might want a larger hash table
12982          * for recovery.  Must be a power of two. */
12983         int               hash_size;
12984         int               hash_shift;
12985         struct list_head *hash_table;
12986 };
12987
12988
12989 /* Utility functions to maintain the revoke table */
12990
12991 /* Borrowed from buffer.c: this is a tried and tested block hash function */
12992 static inline int hash(journal_t *journal, unsigned long block)
12993 {
12994         struct jbd_revoke_table_s *table = journal->j_revoke;
12995         int hash_shift = table->hash_shift;
12996
12997         return ((block << (hash_shift - 6)) ^
12998                 (block >> 13) ^
12999                 (block << (hash_shift - 12))) & (table->hash_size - 1);
13000 }
13001
13002 static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
13003                               tid_t seq)
13004 {
13005         struct list_head *hash_list;
13006         struct jbd_revoke_record_s *record;
13007
13008         record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
13009         if (!record)
13010                 goto oom;
13011
13012         record->sequence = seq;
13013         record->blocknr = blocknr;
13014         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
13015         list_add(&record->hash, hash_list);
13016         return 0;
13017
13018 oom:
13019         return -ENOMEM;
13020 }
13021
13022 /* Find a revoke record in the journal's hash table. */
13023
13024 static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
13025                                                       unsigned long blocknr)
13026 {
13027         struct list_head *hash_list;
13028         struct jbd_revoke_record_s *record;
13029
13030         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
13031
13032         record = (struct jbd_revoke_record_s *) hash_list->next;
13033         while (&(record->hash) != hash_list) {
13034                 if (record->blocknr == blocknr)
13035                         return record;
13036                 record = (struct jbd_revoke_record_s *) record->hash.next;
13037         }
13038         return NULL;
13039 }
13040
13041 int journal_init_revoke_caches(void)
13042 {
13043         revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
13044         if (revoke_record_cache == 0)
13045                 return -ENOMEM;
13046
13047         revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
13048         if (revoke_table_cache == 0) {
13049                 do_cache_destroy(revoke_record_cache);
13050                 revoke_record_cache = NULL;
13051                 return -ENOMEM;
13052         }
13053         return 0;
13054 }
13055
13056 void journal_destroy_revoke_caches(void)
13057 {
13058         do_cache_destroy(revoke_record_cache);
13059         revoke_record_cache = 0;
13060         do_cache_destroy(revoke_table_cache);
13061         revoke_table_cache = 0;
13062 }
13063
13064 /* Initialise the revoke table for a given journal to a given size. */
13065
13066 int journal_init_revoke(journal_t *journal, int hash_size)
13067 {
13068         int shift, tmp;
13069
13070         J_ASSERT (journal->j_revoke == NULL);
13071
13072         journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
13073         if (!journal->j_revoke)
13074                 return -ENOMEM;
13075
13076         /* Check that the hash_size is a power of two */
13077         J_ASSERT ((hash_size & (hash_size-1)) == 0);
13078
13079         journal->j_revoke->hash_size = hash_size;
13080
13081         shift = 0;
13082         tmp = hash_size;
13083         while((tmp >>= 1UL) != 0UL)
13084                 shift++;
13085         journal->j_revoke->hash_shift = shift;
13086
13087         journal->j_revoke->hash_table = malloc(hash_size * sizeof(struct list_head));
13088         if (!journal->j_revoke->hash_table) {
13089                 free(journal->j_revoke);
13090                 journal->j_revoke = NULL;
13091                 return -ENOMEM;
13092         }
13093
13094         for (tmp = 0; tmp < hash_size; tmp++)
13095                 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
13096
13097         return 0;
13098 }
13099
13100 /* Destoy a journal's revoke table.  The table must already be empty! */
13101
13102 void journal_destroy_revoke(journal_t *journal)
13103 {
13104         struct jbd_revoke_table_s *table;
13105         struct list_head *hash_list;
13106         int i;
13107
13108         table = journal->j_revoke;
13109         if (!table)
13110                 return;
13111
13112         for (i=0; i<table->hash_size; i++) {
13113                 hash_list = &table->hash_table[i];
13114                 J_ASSERT (list_empty(hash_list));
13115         }
13116
13117         free(table->hash_table);
13118         free(table);
13119         journal->j_revoke = NULL;
13120 }
13121
13122 /*
13123  * Revoke support for recovery.
13124  *
13125  * Recovery needs to be able to:
13126  *
13127  *  record all revoke records, including the tid of the latest instance
13128  *  of each revoke in the journal
13129  *
13130  *  check whether a given block in a given transaction should be replayed
13131  *  (ie. has not been revoked by a revoke record in that or a subsequent
13132  *  transaction)
13133  *
13134  *  empty the revoke table after recovery.
13135  */
13136
13137 /*
13138  * First, setting revoke records.  We create a new revoke record for
13139  * every block ever revoked in the log as we scan it for recovery, and
13140  * we update the existing records if we find multiple revokes for a
13141  * single block.
13142  */
13143
13144 int journal_set_revoke(journal_t *journal, unsigned long blocknr,
13145                        tid_t sequence)
13146 {
13147         struct jbd_revoke_record_s *record;
13148
13149         record = find_revoke_record(journal, blocknr);
13150         if (record) {
13151                 /* If we have multiple occurences, only record the
13152                  * latest sequence number in the hashed record */
13153                 if (tid_gt(sequence, record->sequence))
13154                         record->sequence = sequence;
13155                 return 0;
13156         }
13157         return insert_revoke_hash(journal, blocknr, sequence);
13158 }
13159
13160 /*
13161  * Test revoke records.  For a given block referenced in the log, has
13162  * that block been revoked?  A revoke record with a given transaction
13163  * sequence number revokes all blocks in that transaction and earlier
13164  * ones, but later transactions still need replayed.
13165  */
13166
13167 int journal_test_revoke(journal_t *journal, unsigned long blocknr,
13168                         tid_t sequence)
13169 {
13170         struct jbd_revoke_record_s *record;
13171
13172         record = find_revoke_record(journal, blocknr);
13173         if (!record)
13174                 return 0;
13175         if (tid_gt(sequence, record->sequence))
13176                 return 0;
13177         return 1;
13178 }
13179
13180 /*
13181  * Finally, once recovery is over, we need to clear the revoke table so
13182  * that it can be reused by the running filesystem.
13183  */
13184
13185 void journal_clear_revoke(journal_t *journal)
13186 {
13187         int i;
13188         struct list_head *hash_list;
13189         struct jbd_revoke_record_s *record;
13190         struct jbd_revoke_table_s *revoke_var;
13191
13192         revoke_var = journal->j_revoke;
13193
13194         for (i = 0; i < revoke_var->hash_size; i++) {
13195                 hash_list = &revoke_var->hash_table[i];
13196                 while (!list_empty(hash_list)) {
13197                         record = (struct jbd_revoke_record_s*) hash_list->next;
13198                         list_del(&record->hash);
13199                         free(record);
13200                 }
13201         }
13202 }
13203
13204 /*
13205  * e2fsck.c - superblock checks
13206  */
13207
13208 #define MIN_CHECK 1
13209 #define MAX_CHECK 2
13210
13211 static void check_super_value(e2fsck_t ctx, const char *descr,
13212                               unsigned long value, int flags,
13213                               unsigned long min_val, unsigned long max_val)
13214 {
13215         struct          problem_context pctx;
13216
13217         if (((flags & MIN_CHECK) && (value < min_val)) ||
13218             ((flags & MAX_CHECK) && (value > max_val))) {
13219                 clear_problem_context(&pctx);
13220                 pctx.num = value;
13221                 pctx.str = descr;
13222                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
13223                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
13224         }
13225 }
13226
13227 /*
13228  * This routine may get stubbed out in special compilations of the
13229  * e2fsck code..
13230  */
13231 #ifndef EXT2_SPECIAL_DEVICE_SIZE
13232 static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
13233 {
13234         return (ext2fs_get_device_size(ctx->filesystem_name,
13235                                        EXT2_BLOCK_SIZE(ctx->fs->super),
13236                                        &ctx->num_blocks));
13237 }
13238 #endif
13239
13240 /*
13241  * helper function to release an inode
13242  */
13243 struct process_block_struct {
13244         e2fsck_t        ctx;
13245         char            *buf;
13246         struct problem_context *pctx;
13247         int             truncating;
13248         int             truncate_offset;
13249         e2_blkcnt_t     truncate_block;
13250         int             truncated_blocks;
13251         int             abort;
13252         errcode_t       errcode;
13253 };
13254
13255 static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
13256                                e2_blkcnt_t blockcnt,
13257                                blk_t    ref_blk FSCK_ATTR((unused)),
13258                                int      ref_offset FSCK_ATTR((unused)),
13259                                void *priv_data)
13260 {
13261         struct process_block_struct *pb;
13262         e2fsck_t                ctx;
13263         struct problem_context  *pctx;
13264         blk_t                   blk = *block_nr;
13265         int                     retval = 0;
13266
13267         pb = (struct process_block_struct *) priv_data;
13268         ctx = pb->ctx;
13269         pctx = pb->pctx;
13270
13271         pctx->blk = blk;
13272         pctx->blkcount = blockcnt;
13273
13274         if (HOLE_BLKADDR(blk))
13275                 return 0;
13276
13277         if ((blk < fs->super->s_first_data_block) ||
13278             (blk >= fs->super->s_blocks_count)) {
13279                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
13280         return_abort:
13281                 pb->abort = 1;
13282                 return BLOCK_ABORT;
13283         }
13284
13285         if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
13286                 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
13287                 goto return_abort;
13288         }
13289
13290         /*
13291          * If we are deleting an orphan, then we leave the fields alone.
13292          * If we are truncating an orphan, then update the inode fields
13293          * and clean up any partial block data.
13294          */
13295         if (pb->truncating) {
13296                 /*
13297                  * We only remove indirect blocks if they are
13298                  * completely empty.
13299                  */
13300                 if (blockcnt < 0) {
13301                         int     i, limit;
13302                         blk_t   *bp;
13303
13304                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
13305                                                         pb->buf);
13306                         if (pb->errcode)
13307                                 goto return_abort;
13308
13309                         limit = fs->blocksize >> 2;
13310                         for (i = 0, bp = (blk_t *) pb->buf;
13311                              i < limit;  i++, bp++)
13312                                 if (*bp)
13313                                         return 0;
13314                 }
13315                 /*
13316                  * We don't remove direct blocks until we've reached
13317                  * the truncation block.
13318                  */
13319                 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
13320                         return 0;
13321                 /*
13322                  * If part of the last block needs truncating, we do
13323                  * it here.
13324                  */
13325                 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
13326                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
13327                                                         pb->buf);
13328                         if (pb->errcode)
13329                                 goto return_abort;
13330                         memset(pb->buf + pb->truncate_offset, 0,
13331                                fs->blocksize - pb->truncate_offset);
13332                         pb->errcode = io_channel_write_blk(fs->io, blk, 1,
13333                                                          pb->buf);
13334                         if (pb->errcode)
13335                                 goto return_abort;
13336                 }
13337                 pb->truncated_blocks++;
13338                 *block_nr = 0;
13339                 retval |= BLOCK_CHANGED;
13340         }
13341
13342         ext2fs_block_alloc_stats(fs, blk, -1);
13343         return retval;
13344 }
13345
13346 /*
13347  * This function releases an inode.  Returns 1 if an inconsistency was
13348  * found.  If the inode has a link count, then it is being truncated and
13349  * not deleted.
13350  */
13351 static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
13352                                 struct ext2_inode *inode, char *block_buf,
13353                                 struct problem_context *pctx)
13354 {
13355         struct process_block_struct     pb;
13356         ext2_filsys                     fs = ctx->fs;
13357         errcode_t                       retval;
13358         __u32                           count;
13359
13360         if (!ext2fs_inode_has_valid_blocks(inode))
13361                 return 0;
13362
13363         pb.buf = block_buf + 3 * ctx->fs->blocksize;
13364         pb.ctx = ctx;
13365         pb.abort = 0;
13366         pb.errcode = 0;
13367         pb.pctx = pctx;
13368         if (inode->i_links_count) {
13369                 pb.truncating = 1;
13370                 pb.truncate_block = (e2_blkcnt_t)
13371                         ((((long long)inode->i_size_high << 32) +
13372                           inode->i_size + fs->blocksize - 1) /
13373                          fs->blocksize);
13374                 pb.truncate_offset = inode->i_size % fs->blocksize;
13375         } else {
13376                 pb.truncating = 0;
13377                 pb.truncate_block = 0;
13378                 pb.truncate_offset = 0;
13379         }
13380         pb.truncated_blocks = 0;
13381         retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
13382                                       block_buf, release_inode_block, &pb);
13383         if (retval) {
13384                 com_err("release_inode_blocks", retval,
13385                         _("while calling ext2fs_block_iterate for inode %d"),
13386                         ino);
13387                 return 1;
13388         }
13389         if (pb.abort)
13390                 return 1;
13391
13392         /* Refresh the inode since ext2fs_block_iterate may have changed it */
13393         e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
13394
13395         if (pb.truncated_blocks)
13396                 inode->i_blocks -= pb.truncated_blocks *
13397                         (fs->blocksize / 512);
13398
13399         if (inode->i_file_acl) {
13400                 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
13401                                                    block_buf, -1, &count);
13402                 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
13403                         retval = 0;
13404                         count = 1;
13405                 }
13406                 if (retval) {
13407                         com_err("release_inode_blocks", retval,
13408                 _("while calling ext2fs_adjust_ea_refocunt for inode %d"),
13409                                 ino);
13410                         return 1;
13411                 }
13412                 if (count == 0)
13413                         ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
13414                 inode->i_file_acl = 0;
13415         }
13416         return 0;
13417 }
13418
13419 /*
13420  * This function releases all of the orphan inodes.  It returns 1 if
13421  * it hit some error, and 0 on success.
13422  */
13423 static int release_orphan_inodes(e2fsck_t ctx)
13424 {
13425         ext2_filsys fs = ctx->fs;
13426         ext2_ino_t      ino, next_ino;
13427         struct ext2_inode inode;
13428         struct problem_context pctx;
13429         char *block_buf;
13430
13431         if ((ino = fs->super->s_last_orphan) == 0)
13432                 return 0;
13433
13434         /*
13435          * Win or lose, we won't be using the head of the orphan inode
13436          * list again.
13437          */
13438         fs->super->s_last_orphan = 0;
13439         ext2fs_mark_super_dirty(fs);
13440
13441         /*
13442          * If the filesystem contains errors, don't run the orphan
13443          * list, since the orphan list can't be trusted; and we're
13444          * going to be running a full e2fsck run anyway...
13445          */
13446         if (fs->super->s_state & EXT2_ERROR_FS)
13447                 return 0;
13448
13449         if ((ino < EXT2_FIRST_INODE(fs->super)) ||
13450             (ino > fs->super->s_inodes_count)) {
13451                 clear_problem_context(&pctx);
13452                 pctx.ino = ino;
13453                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
13454                 return 1;
13455         }
13456
13457         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
13458                                                     "block iterate buffer");
13459         e2fsck_read_bitmaps(ctx);
13460
13461         while (ino) {
13462                 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
13463                 clear_problem_context(&pctx);
13464                 pctx.ino = ino;
13465                 pctx.inode = &inode;
13466                 pctx.str = inode.i_links_count ? _("Truncating") :
13467                         _("Clearing");
13468
13469                 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
13470
13471                 next_ino = inode.i_dtime;
13472                 if (next_ino &&
13473                     ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
13474                      (next_ino > fs->super->s_inodes_count))) {
13475                         pctx.ino = next_ino;
13476                         fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
13477                         goto return_abort;
13478                 }
13479
13480                 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
13481                         goto return_abort;
13482
13483                 if (!inode.i_links_count) {
13484                         ext2fs_inode_alloc_stats2(fs, ino, -1,
13485                                                   LINUX_S_ISDIR(inode.i_mode));
13486                         inode.i_dtime = time(0);
13487                 } else {
13488                         inode.i_dtime = 0;
13489                 }
13490                 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
13491                 ino = next_ino;
13492         }
13493         ext2fs_free_mem(&block_buf);
13494         return 0;
13495 return_abort:
13496         ext2fs_free_mem(&block_buf);
13497         return 1;
13498 }
13499
13500 /*
13501  * Check the resize inode to make sure it is sane.  We check both for
13502  * the case where on-line resizing is not enabled (in which case the
13503  * resize inode should be cleared) as well as the case where on-line
13504  * resizing is enabled.
13505  */
13506 static void check_resize_inode(e2fsck_t ctx)
13507 {
13508         ext2_filsys fs = ctx->fs;
13509         struct ext2_inode inode;
13510         struct problem_context  pctx;
13511         int             i, j, gdt_off, ind_off;
13512         blk_t           blk, pblk, expect;
13513         __u32           *dind_buf = 0, *ind_buf;
13514         errcode_t       retval;
13515
13516         clear_problem_context(&pctx);
13517
13518         /*
13519          * If the resize inode feature isn't set, then
13520          * s_reserved_gdt_blocks must be zero.
13521          */
13522         if (!(fs->super->s_feature_compat &
13523               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
13524                 if (fs->super->s_reserved_gdt_blocks) {
13525                         pctx.num = fs->super->s_reserved_gdt_blocks;
13526                         if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
13527                                         &pctx)) {
13528                                 fs->super->s_reserved_gdt_blocks = 0;
13529                                 ext2fs_mark_super_dirty(fs);
13530                         }
13531                 }
13532         }
13533
13534         /* Read the resize inode */
13535         pctx.ino = EXT2_RESIZE_INO;
13536         retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
13537         if (retval) {
13538                 if (fs->super->s_feature_compat &
13539                     EXT2_FEATURE_COMPAT_RESIZE_INODE)
13540                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
13541                 return;
13542         }
13543
13544         /*
13545          * If the resize inode feature isn't set, check to make sure
13546          * the resize inode is cleared; then we're done.
13547          */
13548         if (!(fs->super->s_feature_compat &
13549               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
13550                 for (i=0; i < EXT2_N_BLOCKS; i++) {
13551                         if (inode.i_block[i])
13552                                 break;
13553                 }
13554                 if ((i < EXT2_N_BLOCKS) &&
13555                     fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
13556                         memset(&inode, 0, sizeof(inode));
13557                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
13558                                            "clear_resize");
13559                 }
13560                 return;
13561         }
13562
13563         /*
13564          * The resize inode feature is enabled; check to make sure the
13565          * only block in use is the double indirect block
13566          */
13567         blk = inode.i_block[EXT2_DIND_BLOCK];
13568         for (i=0; i < EXT2_N_BLOCKS; i++) {
13569                 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
13570                         break;
13571         }
13572         if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
13573             !(inode.i_mode & LINUX_S_IFREG) ||
13574             (blk < fs->super->s_first_data_block ||
13575              blk >= fs->super->s_blocks_count)) {
13576         resize_inode_invalid:
13577                 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
13578                         memset(&inode, 0, sizeof(inode));
13579                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
13580                                            "clear_resize");
13581                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
13582                 }
13583                 if (!(ctx->options & E2F_OPT_READONLY)) {
13584                         fs->super->s_state &= ~EXT2_VALID_FS;
13585                         ext2fs_mark_super_dirty(fs);
13586                 }
13587                 goto cleanup;
13588         }
13589         dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
13590                                                     "resize dind buffer");
13591         ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
13592
13593         retval = ext2fs_read_ind_block(fs, blk, dind_buf);
13594         if (retval)
13595                 goto resize_inode_invalid;
13596
13597         gdt_off = fs->desc_blocks;
13598         pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
13599         for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
13600              i++, gdt_off++, pblk++) {
13601                 gdt_off %= fs->blocksize/4;
13602                 if (dind_buf[gdt_off] != pblk)
13603                         goto resize_inode_invalid;
13604                 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
13605                 if (retval)
13606                         goto resize_inode_invalid;
13607                 ind_off = 0;
13608                 for (j = 1; j < fs->group_desc_count; j++) {
13609                         if (!ext2fs_bg_has_super(fs, j))
13610                                 continue;
13611                         expect = pblk + (j * fs->super->s_blocks_per_group);
13612                         if (ind_buf[ind_off] != expect)
13613                                 goto resize_inode_invalid;
13614                         ind_off++;
13615                 }
13616         }
13617
13618 cleanup:
13619         ext2fs_free_mem(&dind_buf);
13620
13621  }
13622
13623 static void check_super_block(e2fsck_t ctx)
13624 {
13625         ext2_filsys fs = ctx->fs;
13626         blk_t   first_block, last_block;
13627         struct ext2_super_block *sb = fs->super;
13628         struct ext2_group_desc *gd;
13629         blk_t   blocks_per_group = fs->super->s_blocks_per_group;
13630         blk_t   bpg_max;
13631         int     inodes_per_block;
13632         int     ipg_max;
13633         int     inode_size;
13634         dgrp_t  i;
13635         blk_t   should_be;
13636         struct problem_context  pctx;
13637         __u32   free_blocks = 0, free_inodes = 0;
13638
13639         inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
13640         ipg_max = inodes_per_block * (blocks_per_group - 4);
13641         if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
13642                 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
13643         bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
13644         if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
13645                 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
13646
13647         ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
13648                  sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
13649         ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
13650                  sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
13651         ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
13652                 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
13653
13654         clear_problem_context(&pctx);
13655
13656         /*
13657          * Verify the super block constants...
13658          */
13659         check_super_value(ctx, "inodes_count", sb->s_inodes_count,
13660                           MIN_CHECK, 1, 0);
13661         check_super_value(ctx, "blocks_count", sb->s_blocks_count,
13662                           MIN_CHECK, 1, 0);
13663         check_super_value(ctx, "first_data_block", sb->s_first_data_block,
13664                           MAX_CHECK, 0, sb->s_blocks_count);
13665         check_super_value(ctx, "log_block_size", sb->s_log_block_size,
13666                           MIN_CHECK | MAX_CHECK, 0,
13667                           EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
13668         check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
13669                           MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
13670         check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
13671                           MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
13672                           bpg_max);
13673         check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
13674                           MIN_CHECK | MAX_CHECK, 8, bpg_max);
13675         check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
13676                           MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
13677         check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
13678                           MAX_CHECK, 0, sb->s_blocks_count / 2);
13679         check_super_value(ctx, "reserved_gdt_blocks",
13680                           sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
13681                           fs->blocksize/4);
13682         inode_size = EXT2_INODE_SIZE(sb);
13683         check_super_value(ctx, "inode_size",
13684                           inode_size, MIN_CHECK | MAX_CHECK,
13685                           EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
13686         if (inode_size & (inode_size - 1)) {
13687                 pctx.num = inode_size;
13688                 pctx.str = "inode_size";
13689                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
13690                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
13691                 return;
13692         }
13693
13694         if (!ctx->num_blocks) {
13695                 pctx.errcode = e2fsck_get_device_size(ctx);
13696                 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
13697                         fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
13698                         ctx->flags |= E2F_FLAG_ABORT;
13699                         return;
13700                 }
13701                 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
13702                     (ctx->num_blocks < sb->s_blocks_count)) {
13703                         pctx.blk = sb->s_blocks_count;
13704                         pctx.blk2 = ctx->num_blocks;
13705                         if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
13706                                 ctx->flags |= E2F_FLAG_ABORT;
13707                                 return;
13708                         }
13709                 }
13710         }
13711
13712         if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
13713                 pctx.blk = EXT2_BLOCK_SIZE(sb);
13714                 pctx.blk2 = EXT2_FRAG_SIZE(sb);
13715                 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
13716                 ctx->flags |= E2F_FLAG_ABORT;
13717                 return;
13718         }
13719
13720         should_be = sb->s_frags_per_group >>
13721                 (sb->s_log_block_size - sb->s_log_frag_size);
13722         if (sb->s_blocks_per_group != should_be) {
13723                 pctx.blk = sb->s_blocks_per_group;
13724                 pctx.blk2 = should_be;
13725                 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
13726                 ctx->flags |= E2F_FLAG_ABORT;
13727                 return;
13728         }
13729
13730         should_be = (sb->s_log_block_size == 0) ? 1 : 0;
13731         if (sb->s_first_data_block != should_be) {
13732                 pctx.blk = sb->s_first_data_block;
13733                 pctx.blk2 = should_be;
13734                 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
13735                 ctx->flags |= E2F_FLAG_ABORT;
13736                 return;
13737         }
13738
13739         should_be = sb->s_inodes_per_group * fs->group_desc_count;
13740         if (sb->s_inodes_count != should_be) {
13741                 pctx.ino = sb->s_inodes_count;
13742                 pctx.ino2 = should_be;
13743                 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
13744                         sb->s_inodes_count = should_be;
13745                         ext2fs_mark_super_dirty(fs);
13746                 }
13747         }
13748
13749         /*
13750          * Verify the group descriptors....
13751          */
13752         first_block =  sb->s_first_data_block;
13753         last_block = first_block + blocks_per_group;
13754
13755         for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
13756                 pctx.group = i;
13757
13758                 if (i == fs->group_desc_count - 1)
13759                         last_block = sb->s_blocks_count;
13760                 if ((gd->bg_block_bitmap < first_block) ||
13761                     (gd->bg_block_bitmap >= last_block)) {
13762                         pctx.blk = gd->bg_block_bitmap;
13763                         if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
13764                                 gd->bg_block_bitmap = 0;
13765                 }
13766                 if (gd->bg_block_bitmap == 0) {
13767                         ctx->invalid_block_bitmap_flag[i]++;
13768                         ctx->invalid_bitmaps++;
13769                 }
13770                 if ((gd->bg_inode_bitmap < first_block) ||
13771                     (gd->bg_inode_bitmap >= last_block)) {
13772                         pctx.blk = gd->bg_inode_bitmap;
13773                         if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
13774                                 gd->bg_inode_bitmap = 0;
13775                 }
13776                 if (gd->bg_inode_bitmap == 0) {
13777                         ctx->invalid_inode_bitmap_flag[i]++;
13778                         ctx->invalid_bitmaps++;
13779                 }
13780                 if ((gd->bg_inode_table < first_block) ||
13781                     ((gd->bg_inode_table +
13782                       fs->inode_blocks_per_group - 1) >= last_block)) {
13783                         pctx.blk = gd->bg_inode_table;
13784                         if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
13785                                 gd->bg_inode_table = 0;
13786                 }
13787                 if (gd->bg_inode_table == 0) {
13788                         ctx->invalid_inode_table_flag[i]++;
13789                         ctx->invalid_bitmaps++;
13790                 }
13791                 free_blocks += gd->bg_free_blocks_count;
13792                 free_inodes += gd->bg_free_inodes_count;
13793                 first_block += sb->s_blocks_per_group;
13794                 last_block += sb->s_blocks_per_group;
13795
13796                 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
13797                     (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
13798                     (gd->bg_used_dirs_count > sb->s_inodes_per_group))
13799                         ext2fs_unmark_valid(fs);
13800
13801         }
13802
13803         /*
13804          * Update the global counts from the block group counts.  This
13805          * is needed for an experimental patch which eliminates
13806          * locking the entire filesystem when allocating blocks or
13807          * inodes; if the filesystem is not unmounted cleanly, the
13808          * global counts may not be accurate.
13809          */
13810         if ((free_blocks != sb->s_free_blocks_count) ||
13811             (free_inodes != sb->s_free_inodes_count)) {
13812                 if (ctx->options & E2F_OPT_READONLY)
13813                         ext2fs_unmark_valid(fs);
13814                 else {
13815                         sb->s_free_blocks_count = free_blocks;
13816                         sb->s_free_inodes_count = free_inodes;
13817                         ext2fs_mark_super_dirty(fs);
13818                 }
13819         }
13820
13821         if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
13822             (sb->s_free_inodes_count > sb->s_inodes_count))
13823                 ext2fs_unmark_valid(fs);
13824
13825
13826         /*
13827          * If we have invalid bitmaps, set the error state of the
13828          * filesystem.
13829          */
13830         if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
13831                 sb->s_state &= ~EXT2_VALID_FS;
13832                 ext2fs_mark_super_dirty(fs);
13833         }
13834
13835         clear_problem_context(&pctx);
13836
13837 #ifndef EXT2_SKIP_UUID
13838         /*
13839          * If the UUID field isn't assigned, assign it.
13840          */
13841         if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
13842                 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
13843                         uuid_generate(sb->s_uuid);
13844                         ext2fs_mark_super_dirty(fs);
13845                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
13846                 }
13847         }
13848 #endif
13849
13850         /*
13851          * For the Hurd, check to see if the filetype option is set,
13852          * since it doesn't support it.
13853          */
13854         if (!(ctx->options & E2F_OPT_READONLY) &&
13855             fs->super->s_creator_os == EXT2_OS_HURD &&
13856             (fs->super->s_feature_incompat &
13857              EXT2_FEATURE_INCOMPAT_FILETYPE)) {
13858                 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
13859                         fs->super->s_feature_incompat &=
13860                                 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
13861                         ext2fs_mark_super_dirty(fs);
13862
13863                 }
13864         }
13865
13866         /*
13867          * If we have any of the compatibility flags set, we need to have a
13868          * revision 1 filesystem.  Most kernels will not check the flags on
13869          * a rev 0 filesystem and we may have corruption issues because of
13870          * the incompatible changes to the filesystem.
13871          */
13872         if (!(ctx->options & E2F_OPT_READONLY) &&
13873             fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
13874             (fs->super->s_feature_compat ||
13875              fs->super->s_feature_ro_compat ||
13876              fs->super->s_feature_incompat) &&
13877             fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
13878                 ext2fs_update_dynamic_rev(fs);
13879                 ext2fs_mark_super_dirty(fs);
13880         }
13881
13882         check_resize_inode(ctx);
13883
13884         /*
13885          * Clean up any orphan inodes, if present.
13886          */
13887         if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
13888                 fs->super->s_state &= ~EXT2_VALID_FS;
13889                 ext2fs_mark_super_dirty(fs);
13890         }
13891
13892         /*
13893          * Move the ext3 journal file, if necessary.
13894          */
13895         e2fsck_move_ext3_journal(ctx);
13896         return;
13897 }
13898
13899 /*
13900  * swapfs.c --- byte-swap an ext2 filesystem
13901  */
13902
13903 #ifdef ENABLE_SWAPFS
13904
13905 struct swap_block_struct {
13906         ext2_ino_t      ino;
13907         int             isdir;
13908         errcode_t       errcode;
13909         char            *dir_buf;
13910         struct ext2_inode *inode;
13911 };
13912
13913 /*
13914  * This is a helper function for block_iterate.  We mark all of the
13915  * indirect and direct blocks as changed, so that block_iterate will
13916  * write them out.
13917  */
13918 static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
13919                       void *priv_data)
13920 {
13921         errcode_t       retval;
13922
13923         struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
13924
13925         if (sb->isdir && (blockcnt >= 0) && *block_nr) {
13926                 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
13927                 if (retval) {
13928                         sb->errcode = retval;
13929                         return BLOCK_ABORT;
13930                 }
13931                 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
13932                 if (retval) {
13933                         sb->errcode = retval;
13934                         return BLOCK_ABORT;
13935                 }
13936         }
13937         if (blockcnt >= 0) {
13938                 if (blockcnt < EXT2_NDIR_BLOCKS)
13939                         return 0;
13940                 return BLOCK_CHANGED;
13941         }
13942         if (blockcnt == BLOCK_COUNT_IND) {
13943                 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
13944                         return 0;
13945                 return BLOCK_CHANGED;
13946         }
13947         if (blockcnt == BLOCK_COUNT_DIND) {
13948                 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
13949                         return 0;
13950                 return BLOCK_CHANGED;
13951         }
13952         if (blockcnt == BLOCK_COUNT_TIND) {
13953                 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
13954                         return 0;
13955                 return BLOCK_CHANGED;
13956         }
13957         return BLOCK_CHANGED;
13958 }
13959
13960 /*
13961  * This function is responsible for byte-swapping all of the indirect,
13962  * block pointers.  It is also responsible for byte-swapping directories.
13963  */
13964 static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
13965                               struct ext2_inode *inode)
13966 {
13967         errcode_t                       retval;
13968         struct swap_block_struct        sb;
13969
13970         sb.ino = ino;
13971         sb.inode = inode;
13972         sb.dir_buf = block_buf + ctx->fs->blocksize*3;
13973         sb.errcode = 0;
13974         sb.isdir = 0;
13975         if (LINUX_S_ISDIR(inode->i_mode))
13976                 sb.isdir = 1;
13977
13978         retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
13979                                       swap_block, &sb);
13980         if (retval) {
13981                 com_err("swap_inode_blocks", retval,
13982                         _("while calling ext2fs_block_iterate"));
13983                 ctx->flags |= E2F_FLAG_ABORT;
13984                 return;
13985         }
13986         if (sb.errcode) {
13987                 com_err("swap_inode_blocks", sb.errcode,
13988                         _("while calling iterator function"));
13989                 ctx->flags |= E2F_FLAG_ABORT;
13990                 return;
13991         }
13992 }
13993
13994 static void swap_inodes(e2fsck_t ctx)
13995 {
13996         ext2_filsys fs = ctx->fs;
13997         dgrp_t                  group;
13998         unsigned int            i;
13999         ext2_ino_t              ino = 1;
14000         char                    *buf, *block_buf;
14001         errcode_t               retval;
14002         struct ext2_inode *     inode;
14003
14004         e2fsck_use_inode_shortcuts(ctx, 1);
14005
14006         retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
14007                                 &buf);
14008         if (retval) {
14009                 com_err("swap_inodes", retval,
14010                         _("while allocating inode buffer"));
14011                 ctx->flags |= E2F_FLAG_ABORT;
14012                 return;
14013         }
14014         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
14015                                                     "block interate buffer");
14016         for (group = 0; group < fs->group_desc_count; group++) {
14017                 retval = io_channel_read_blk(fs->io,
14018                       fs->group_desc[group].bg_inode_table,
14019                       fs->inode_blocks_per_group, buf);
14020                 if (retval) {
14021                         com_err("swap_inodes", retval,
14022                                 _("while reading inode table (group %d)"),
14023                                 group);
14024                         ctx->flags |= E2F_FLAG_ABORT;
14025                         return;
14026                 }
14027                 inode = (struct ext2_inode *) buf;
14028                 for (i=0; i < fs->super->s_inodes_per_group;
14029                      i++, ino++, inode++) {
14030                         ctx->stashed_ino = ino;
14031                         ctx->stashed_inode = inode;
14032
14033                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
14034                                 ext2fs_swap_inode(fs, inode, inode, 0);
14035
14036                         /*
14037                          * Skip deleted files.
14038                          */
14039                         if (inode->i_links_count == 0)
14040                                 continue;
14041
14042                         if (LINUX_S_ISDIR(inode->i_mode) ||
14043                             ((inode->i_block[EXT2_IND_BLOCK] ||
14044                               inode->i_block[EXT2_DIND_BLOCK] ||
14045                               inode->i_block[EXT2_TIND_BLOCK]) &&
14046                              ext2fs_inode_has_valid_blocks(inode)))
14047                                 swap_inode_blocks(ctx, ino, block_buf, inode);
14048
14049                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
14050                                 return;
14051
14052                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
14053                                 ext2fs_swap_inode(fs, inode, inode, 1);
14054                 }
14055                 retval = io_channel_write_blk(fs->io,
14056                       fs->group_desc[group].bg_inode_table,
14057                       fs->inode_blocks_per_group, buf);
14058                 if (retval) {
14059                         com_err("swap_inodes", retval,
14060                                 _("while writing inode table (group %d)"),
14061                                 group);
14062                         ctx->flags |= E2F_FLAG_ABORT;
14063                         return;
14064                 }
14065         }
14066         ext2fs_free_mem(&buf);
14067         ext2fs_free_mem(&block_buf);
14068         e2fsck_use_inode_shortcuts(ctx, 0);
14069         ext2fs_flush_icache(fs);
14070 }
14071
14072 #if defined(__powerpc__) && defined(EXT2FS_ENABLE_SWAPFS)
14073 /*
14074  * On the PowerPC, the big-endian variant of the ext2 filesystem
14075  * has its bitmaps stored as 32-bit words with bit 0 as the LSB
14076  * of each word.  Thus a bitmap with only bit 0 set would be, as
14077  * a string of bytes, 00 00 00 01 00 ...
14078  * To cope with this, we byte-reverse each word of a bitmap if
14079  * we have a big-endian filesystem, that is, if we are *not*
14080  * byte-swapping other word-sized numbers.
14081  */
14082 #define EXT2_BIG_ENDIAN_BITMAPS
14083 #endif
14084
14085 #ifdef EXT2_BIG_ENDIAN_BITMAPS
14086 static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
14087 {
14088         __u32 *p = (__u32 *) bmap->bitmap;
14089         int n, nbytes = (bmap->end - bmap->start + 7) / 8;
14090
14091         for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
14092                 *p = ext2fs_swab32(*p);
14093 }
14094 #endif
14095
14096
14097 #ifdef ENABLE_SWAPFS
14098 static void swap_filesys(e2fsck_t ctx)
14099 {
14100         ext2_filsys fs = ctx->fs;
14101 #ifdef RESOURCE_TRACK
14102         struct resource_track   rtrack;
14103
14104         init_resource_track(&rtrack);
14105 #endif
14106
14107         if (!(ctx->options & E2F_OPT_PREEN))
14108                 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
14109
14110 #ifdef MTRACE
14111         mtrace_print("Byte swap");
14112 #endif
14113
14114         if (fs->super->s_mnt_count) {
14115                 fprintf(stderr, _("%s: the filesystem must be freshly "
14116                         "checked using fsck\n"
14117                         "and not mounted before trying to "
14118                         "byte-swap it.\n"), ctx->device_name);
14119                 ctx->flags |= E2F_FLAG_ABORT;
14120                 return;
14121         }
14122         if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
14123                 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
14124                                EXT2_FLAG_SWAP_BYTES_WRITE);
14125                 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
14126         } else {
14127                 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
14128                 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
14129         }
14130         swap_inodes(ctx);
14131         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
14132                 return;
14133         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
14134                 fs->flags |= EXT2_FLAG_SWAP_BYTES;
14135         fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
14136                        EXT2_FLAG_SWAP_BYTES_WRITE);
14137
14138 #ifdef EXT2_BIG_ENDIAN_BITMAPS
14139         e2fsck_read_bitmaps(ctx);
14140         ext2fs_swap_bitmap(fs->inode_map);
14141         ext2fs_swap_bitmap(fs->block_map);
14142         fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
14143 #endif
14144         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
14145         ext2fs_flush(fs);
14146         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
14147
14148 #ifdef RESOURCE_TRACK
14149         if (ctx->options & E2F_OPT_TIME2)
14150                 print_resource_track(_("Byte swap"), &rtrack);
14151 #endif
14152 }
14153 #endif  /* ENABLE_SWAPFS */
14154
14155 #endif
14156
14157 /*
14158  * util.c --- miscellaneous utilities
14159  */
14160
14161 #ifdef HAVE_CONIO_H
14162 #undef HAVE_TERMIOS_H
14163 #include <conio.h>
14164 #define read_a_char()   getch()
14165 #else
14166 #ifdef HAVE_TERMIOS_H
14167 #include <termios.h>
14168 #endif
14169 #endif
14170
14171 #if 0
14172 void fatal_error(e2fsck_t ctx, const char *msg)
14173 {
14174         if (msg)
14175                 fprintf (stderr, "e2fsck: %s\n", msg);
14176         if (ctx->fs && ctx->fs->io) {
14177                 if (ctx->fs->io->magic == EXT2_ET_MAGIC_IO_CHANNEL)
14178                         io_channel_flush(ctx->fs->io);
14179                 else
14180                         fprintf(stderr, "e2fsck: io manager magic bad!\n");
14181         }
14182         ctx->flags |= E2F_FLAG_ABORT;
14183         if (ctx->flags & E2F_FLAG_SETJMP_OK)
14184                 longjmp(ctx->abort_loc, 1);
14185         exit(EXIT_ERROR);
14186 }
14187 #endif
14188
14189 void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
14190                              const char *description)
14191 {
14192         void *ret;
14193         char buf[256];
14194
14195 #ifdef DEBUG_ALLOCATE_MEMORY
14196         printf("Allocating %d bytes for %s...\n", size, description);
14197 #endif
14198         ret = malloc(size);
14199         if (!ret) {
14200                 sprintf(buf, "Can't allocate %s\n", description);
14201                 fatal_error(ctx, buf);
14202         }
14203         memset(ret, 0, size);
14204         return ret;
14205 }
14206
14207 static char *string_copy(const char *str, int len)
14208 {
14209         char    *ret;
14210
14211         if (!str)
14212                 return NULL;
14213         if (!len)
14214                 len = strlen(str);
14215         ret = malloc(len+1);
14216         if (ret) {
14217                 strncpy(ret, str, len);
14218                 ret[len] = 0;
14219         }
14220         return ret;
14221 }
14222
14223 #ifndef HAVE_CONIO_H
14224 static int read_a_char(void)
14225 {
14226         char    c;
14227         int     r;
14228         int     fail = 0;
14229
14230         while(1) {
14231                 if (e2fsck_global_ctx &&
14232                     (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
14233                         return 3;
14234                 }
14235                 r = read(0, &c, 1);
14236                 if (r == 1)
14237                         return c;
14238                 if (fail++ > 100)
14239                         break;
14240         }
14241         return EOF;
14242 }
14243 #endif
14244
14245 static int ask_yn(const char * string, int def)
14246 {
14247         int             c;
14248         const char      *defstr;
14249         static const char short_yes[] = "yY";
14250         static const char short_no[] = "nN";
14251
14252 #ifdef HAVE_TERMIOS_H
14253         struct termios  termios, tmp;
14254
14255         tcgetattr (0, &termios);
14256         tmp = termios;
14257         tmp.c_lflag &= ~(ICANON | ECHO);
14258         tmp.c_cc[VMIN] = 1;
14259         tmp.c_cc[VTIME] = 0;
14260         tcsetattr (0, TCSANOW, &tmp);
14261 #endif
14262
14263         if (def == 1)
14264                 defstr = "<y>";
14265         else if (def == 0)
14266                 defstr = "<n>";
14267         else
14268                 defstr = " (y/n)";
14269         printf("%s%s? ", string, defstr);
14270         while (1) {
14271                 fflush (stdout);
14272                 if ((c = read_a_char()) == EOF)
14273                         break;
14274                 if (c == 3) {
14275 #ifdef HAVE_TERMIOS_H
14276                         tcsetattr (0, TCSANOW, &termios);
14277 #endif
14278                         if (e2fsck_global_ctx &&
14279                             e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
14280                                 puts("\n");
14281                                 longjmp(e2fsck_global_ctx->abort_loc, 1);
14282                         }
14283                         puts(_("cancelled!\n"));
14284                         return 0;
14285                 }
14286                 if (strchr(short_yes, (char) c)) {
14287                         def = 1;
14288                         break;
14289                 }
14290                 else if (strchr(short_no, (char) c)) {
14291                         def = 0;
14292                         break;
14293                 }
14294                 else if ((c == ' ' || c == '\n') && (def != -1))
14295                         break;
14296         }
14297         if (def)
14298                 puts("yes\n");
14299         else
14300                 puts ("no\n");
14301 #ifdef HAVE_TERMIOS_H
14302         tcsetattr (0, TCSANOW, &termios);
14303 #endif
14304         return def;
14305 }
14306
14307 int ask (e2fsck_t ctx, const char * string, int def)
14308 {
14309         if (ctx->options & E2F_OPT_NO) {
14310                 printf (_("%s? no\n\n"), string);
14311                 return 0;
14312         }
14313         if (ctx->options & E2F_OPT_YES) {
14314                 printf (_("%s? yes\n\n"), string);
14315                 return 1;
14316         }
14317         if (ctx->options & E2F_OPT_PREEN) {
14318                 printf ("%s? %s\n\n", string, def ? _("yes") : _("no"));
14319                 return def;
14320         }
14321         return ask_yn(string, def);
14322 }
14323
14324 void e2fsck_read_bitmaps(e2fsck_t ctx)
14325 {
14326         ext2_filsys fs = ctx->fs;
14327         errcode_t       retval;
14328
14329         if (ctx->invalid_bitmaps) {
14330                 com_err(ctx->program_name, 0,
14331                     _("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
14332                         ctx->device_name);
14333                 fatal_error(ctx, 0);
14334         }
14335
14336         ehandler_operation(_("reading inode and block bitmaps"));
14337         retval = ext2fs_read_bitmaps(fs);
14338         ehandler_operation(0);
14339         if (retval) {
14340                 com_err(ctx->program_name, retval,
14341                         _("while retrying to read bitmaps for %s"),
14342                         ctx->device_name);
14343                 fatal_error(ctx, 0);
14344         }
14345 }
14346
14347 static void e2fsck_write_bitmaps(e2fsck_t ctx)
14348 {
14349         ext2_filsys fs = ctx->fs;
14350         errcode_t       retval;
14351
14352         if (ext2fs_test_bb_dirty(fs)) {
14353                 ehandler_operation(_("writing block bitmaps"));
14354                 retval = ext2fs_write_block_bitmap(fs);
14355                 ehandler_operation(0);
14356                 if (retval) {
14357                         com_err(ctx->program_name, retval,
14358                             _("while retrying to write block bitmaps for %s"),
14359                                 ctx->device_name);
14360                         fatal_error(ctx, 0);
14361                 }
14362         }
14363
14364         if (ext2fs_test_ib_dirty(fs)) {
14365                 ehandler_operation(_("writing inode bitmaps"));
14366                 retval = ext2fs_write_inode_bitmap(fs);
14367                 ehandler_operation(0);
14368                 if (retval) {
14369                         com_err(ctx->program_name, retval,
14370                             _("while retrying to write inode bitmaps for %s"),
14371                                 ctx->device_name);
14372                         fatal_error(ctx, 0);
14373                 }
14374         }
14375 }
14376
14377 void preenhalt(e2fsck_t ctx)
14378 {
14379         ext2_filsys fs = ctx->fs;
14380
14381         if (!(ctx->options & E2F_OPT_PREEN))
14382                 return;
14383         fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
14384                 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
14385                ctx->device_name);
14386         if (fs != NULL) {
14387                 fs->super->s_state |= EXT2_ERROR_FS;
14388                 ext2fs_mark_super_dirty(fs);
14389                 ext2fs_close(fs);
14390         }
14391         exit(EXIT_UNCORRECTED);
14392 }
14393
14394 #ifdef RESOURCE_TRACK
14395 void init_resource_track(struct resource_track *track)
14396 {
14397 #ifdef HAVE_GETRUSAGE
14398         struct rusage r;
14399 #endif
14400
14401         track->brk_start = sbrk(0);
14402         gettimeofday(&track->time_start, 0);
14403 #ifdef HAVE_GETRUSAGE
14404 #ifdef sun
14405         memset(&r, 0, sizeof(struct rusage));
14406 #endif
14407         getrusage(RUSAGE_SELF, &r);
14408         track->user_start = r.ru_utime;
14409         track->system_start = r.ru_stime;
14410 #else
14411         track->user_start.tv_sec = track->user_start.tv_usec = 0;
14412         track->system_start.tv_sec = track->system_start.tv_usec = 0;
14413 #endif
14414 }
14415
14416 static _INLINE_ float timeval_subtract(struct timeval *tv1,
14417                                        struct timeval *tv2)
14418 {
14419         return ((tv1->tv_sec - tv2->tv_sec) +
14420                 ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
14421 }
14422
14423 void print_resource_track(const char *desc, struct resource_track *track)
14424 {
14425 #ifdef HAVE_GETRUSAGE
14426         struct rusage r;
14427 #endif
14428 #ifdef HAVE_MALLINFO
14429         struct mallinfo malloc_info;
14430 #endif
14431         struct timeval time_end;
14432
14433         gettimeofday(&time_end, 0);
14434
14435         if (desc)
14436                 printf("%s: ", desc);
14437
14438 #ifdef HAVE_MALLINFO
14439 #define kbytes(x)       (((x) + 1023) / 1024)
14440
14441         malloc_info = mallinfo();
14442         printf(_("Memory used: %dk/%dk (%dk/%dk), "),
14443                kbytes(malloc_info.arena), kbytes(malloc_info.hblkhd),
14444                kbytes(malloc_info.uordblks), kbytes(malloc_info.fordblks));
14445 #else
14446         printf(_("Memory used: %d, "),
14447                (int) (((char *) sbrk(0)) - ((char *) track->brk_start)));
14448 #endif
14449 #ifdef HAVE_GETRUSAGE
14450         getrusage(RUSAGE_SELF, &r);
14451
14452         printf(_("time: %5.2f/%5.2f/%5.2f\n"),
14453                timeval_subtract(&time_end, &track->time_start),
14454                timeval_subtract(&r.ru_utime, &track->user_start),
14455                timeval_subtract(&r.ru_stime, &track->system_start));
14456 #else
14457         printf(_("elapsed time: %6.3f\n"),
14458                timeval_subtract(&time_end, &track->time_start));
14459 #endif
14460 }
14461 #endif /* RESOURCE_TRACK */
14462
14463 void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
14464                               struct ext2_inode * inode, const char *proc)
14465 {
14466         int retval;
14467
14468         retval = ext2fs_read_inode(ctx->fs, ino, inode);
14469         if (retval) {
14470                 com_err("ext2fs_read_inode", retval,
14471                         _("while reading inode %ld in %s"), ino, proc);
14472                 fatal_error(ctx, 0);
14473         }
14474 }
14475
14476 extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
14477                                struct ext2_inode * inode, int bufsize,
14478                                const char *proc)
14479 {
14480         int retval;
14481
14482         retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
14483         if (retval) {
14484                 com_err("ext2fs_write_inode", retval,
14485                         _("while writing inode %ld in %s"), ino, proc);
14486                 fatal_error(ctx, 0);
14487         }
14488 }
14489
14490 extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
14491                                struct ext2_inode * inode, const char *proc)
14492 {
14493         int retval;
14494
14495         retval = ext2fs_write_inode(ctx->fs, ino, inode);
14496         if (retval) {
14497                 com_err("ext2fs_write_inode", retval,
14498                         _("while writing inode %ld in %s"), ino, proc);
14499                 fatal_error(ctx, 0);
14500         }
14501 }
14502
14503 #ifdef MTRACE
14504 void mtrace_print(char *mesg)
14505 {
14506         FILE    *malloc_get_mallstream();
14507         FILE    *f = malloc_get_mallstream();
14508
14509         if (f)
14510                 fprintf(f, "============= %s\n", mesg);
14511 }
14512 #endif
14513
14514 blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
14515                    io_manager manager)
14516 {
14517         struct ext2_super_block *sb;
14518         io_channel              io = NULL;
14519         void                    *buf = NULL;
14520         int                     blocksize;
14521         blk_t                   superblock, ret_sb = 8193;
14522
14523         if (fs && fs->super) {
14524                 ret_sb = (fs->super->s_blocks_per_group +
14525                           fs->super->s_first_data_block);
14526                 if (ctx) {
14527                         ctx->superblock = ret_sb;
14528                         ctx->blocksize = fs->blocksize;
14529                 }
14530                 return ret_sb;
14531         }
14532
14533         if (ctx) {
14534                 if (ctx->blocksize) {
14535                         ret_sb = ctx->blocksize * 8;
14536                         if (ctx->blocksize == 1024)
14537                                 ret_sb++;
14538                         ctx->superblock = ret_sb;
14539                         return ret_sb;
14540                 }
14541                 ctx->superblock = ret_sb;
14542                 ctx->blocksize = 1024;
14543         }
14544
14545         if (!name || !manager)
14546                 goto cleanup;
14547
14548         if (manager->open(name, 0, &io) != 0)
14549                 goto cleanup;
14550
14551         if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
14552                 goto cleanup;
14553         sb = (struct ext2_super_block *) buf;
14554
14555         for (blocksize = EXT2_MIN_BLOCK_SIZE;
14556              blocksize <= EXT2_MAX_BLOCK_SIZE ; blocksize *= 2) {
14557                 superblock = blocksize*8;
14558                 if (blocksize == 1024)
14559                         superblock++;
14560                 io_channel_set_blksize(io, blocksize);
14561                 if (io_channel_read_blk(io, superblock,
14562                                         -SUPERBLOCK_SIZE, buf))
14563                         continue;
14564 #ifdef EXT2FS_ENABLE_SWAPFS
14565                 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
14566                         ext2fs_swap_super(sb);
14567 #endif
14568                 if (sb->s_magic == EXT2_SUPER_MAGIC) {
14569                         ret_sb = superblock;
14570                         if (ctx) {
14571                                 ctx->superblock = superblock;
14572                                 ctx->blocksize = blocksize;
14573                         }
14574                         break;
14575                 }
14576         }
14577
14578 cleanup:
14579         if (io)
14580                 io_channel_close(io);
14581         ext2fs_free_mem(&buf);
14582         return (ret_sb);
14583 }
14584
14585
14586 /*
14587  * This function runs through the e2fsck passes and calls them all,
14588  * returning restart, abort, or cancel as necessary...
14589  */
14590 typedef void (*pass_t)(e2fsck_t ctx);
14591
14592 static const pass_t e2fsck_passes[] = {
14593         e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
14594         e2fsck_pass5, 0 };
14595
14596 #define E2F_FLAG_RUN_RETURN     (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
14597
14598 static int e2fsck_run(e2fsck_t ctx)
14599 {
14600         int     i;
14601         pass_t  e2fsck_pass;
14602
14603         if (setjmp(ctx->abort_loc)) {
14604                 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
14605                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
14606         }
14607         ctx->flags |= E2F_FLAG_SETJMP_OK;
14608
14609         for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
14610                 if (ctx->flags & E2F_FLAG_RUN_RETURN)
14611                         break;
14612                 e2fsck_pass(ctx);
14613                 if (ctx->progress)
14614                         (void) (ctx->progress)(ctx, 0, 0, 0);
14615         }
14616         ctx->flags &= ~E2F_FLAG_SETJMP_OK;
14617
14618         if (ctx->flags & E2F_FLAG_RUN_RETURN)
14619                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
14620         return 0;
14621 }
14622
14623
14624 /*
14625  * unix.c - The unix-specific code for e2fsck
14626  */
14627
14628
14629 /* Command line options */
14630 static int swapfs;
14631 #ifdef ENABLE_SWAPFS
14632 static int normalize_swapfs;
14633 #endif
14634 static int cflag;               /* check disk */
14635 static int show_version_only;
14636 static int verbose;
14637
14638 static int replace_bad_blocks;
14639 static int keep_bad_blocks;
14640 static char *bad_blocks_file;
14641
14642 #ifdef __CONFIG_JBD_DEBUG__E2FS         /* Enabled by configure --enable-jfs-debug */
14643 int journal_enable_debug = -1;
14644 #endif
14645
14646 #if 0
14647 static void usage(e2fsck_t ctx)
14648 {
14649         fprintf(stderr,
14650                 _("Usage: %s [-panyrcdfvstDFSV] [-b superblock] [-B blocksize]\n"
14651                 "\t\t[-I inode_buffer_blocks] [-P process_inode_size]\n"
14652                 "\t\t[-l|-L bad_blocks_file] [-C fd] [-j external_journal]\n"
14653                 "\t\t[-E extended-options] device\n"),
14654                 ctx->program_name);
14655
14656         fprintf(stderr, _("\nEmergency help:\n"
14657                 " -p                   Automatic repair (no questions)\n"
14658                 " -n                   Make no changes to the filesystem\n"
14659                 " -y                   Assume \"yes\" to all questions\n"
14660                 " -c                   Check for bad blocks and add them to the badblock list\n"
14661                 " -f                   Force checking even if filesystem is marked clean\n"));
14662         fprintf(stderr, _(""
14663                 " -v                   Be verbose\n"
14664                 " -b superblock        Use alternative superblock\n"
14665                 " -B blocksize         Force blocksize when looking for superblock\n"
14666                 " -j external_journal  Set location of the external journal\n"
14667                 " -l bad_blocks_file   Add to badblocks list\n"
14668                 " -L bad_blocks_file   Set badblocks list\n"
14669                 ));
14670
14671         exit(EXIT_USAGE);
14672 }
14673 #endif
14674
14675 #define P_E2(singular, plural, n)       n, ((n) == 1 ? singular : plural)
14676
14677 static void show_stats(e2fsck_t ctx)
14678 {
14679         ext2_filsys fs = ctx->fs;
14680         int inodes, inodes_used, blocks, blocks_used;
14681         int dir_links;
14682         int num_files, num_links;
14683         int frag_percent;
14684
14685         dir_links = 2 * ctx->fs_directory_count - 1;
14686         num_files = ctx->fs_total_count - dir_links;
14687         num_links = ctx->fs_links_count - dir_links;
14688         inodes = fs->super->s_inodes_count;
14689         inodes_used = (fs->super->s_inodes_count -
14690                        fs->super->s_free_inodes_count);
14691         blocks = fs->super->s_blocks_count;
14692         blocks_used = (fs->super->s_blocks_count -
14693                        fs->super->s_free_blocks_count);
14694
14695         frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
14696         frag_percent = (frag_percent + 5) / 10;
14697
14698         if (!verbose) {
14699                 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
14700                        ctx->device_name, inodes_used, inodes,
14701                        frag_percent / 10, frag_percent % 10,
14702                        blocks_used, blocks);
14703                 return;
14704         }
14705         printf ("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
14706                 100 * inodes_used / inodes);
14707         printf ("%8d non-contiguous inode%s (%0d.%d%%)\n",
14708                 P_E2("", "s", ctx->fs_fragmented),
14709                 frag_percent / 10, frag_percent % 10);
14710         printf (_("         # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
14711                 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
14712         printf ("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
14713                 (int) ((long long) 100 * blocks_used / blocks));
14714         printf ("%8d bad block%s\n", P_E2("", "s", ctx->fs_badblocks_count));
14715         printf ("%8d large file%s\n", P_E2("", "s", ctx->large_files));
14716         printf ("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
14717         printf ("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
14718         printf ("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
14719         printf ("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
14720         printf ("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
14721         printf ("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
14722         printf ("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
14723         printf (" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
14724         printf ("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
14725         printf ("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
14726 }
14727
14728 static void check_mount(e2fsck_t ctx)
14729 {
14730         errcode_t       retval;
14731         int             cont;
14732
14733         retval = ext2fs_check_if_mounted(ctx->filesystem_name,
14734                                          &ctx->mount_flags);
14735         if (retval) {
14736                 com_err("ext2fs_check_if_mount", retval,
14737                         _("while determining whether %s is mounted."),
14738                         ctx->filesystem_name);
14739                 return;
14740         }
14741
14742         /*
14743          * If the filesystem isn't mounted, or it's the root filesystem
14744          * and it's mounted read-only, then everything's fine.
14745          */
14746         if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
14747             ((ctx->mount_flags & EXT2_MF_ISROOT) &&
14748              (ctx->mount_flags & EXT2_MF_READONLY)))
14749                 return;
14750
14751         if (ctx->options & E2F_OPT_READONLY) {
14752                 printf(_("Warning!  %s is mounted.\n"), ctx->filesystem_name);
14753                 return;
14754         }
14755
14756         printf(_("%s is mounted.  "), ctx->filesystem_name);
14757         if (!ctx->interactive)
14758                 fatal_error(ctx, _("Cannot continue, aborting.\n\n"));
14759         printf(_("\n\n\007\007\007\007WARNING!!!  "
14760                "Running e2fsck on a mounted filesystem may cause\n"
14761                "SEVERE filesystem damage.\007\007\007\n\n"));
14762         cont = ask_yn(_("Do you really want to continue"), -1);
14763         if (!cont) {
14764                 printf (_("check aborted.\n"));
14765                 exit (0);
14766         }
14767         return;
14768 }
14769
14770 static int is_on_batt(void)
14771 {
14772         FILE    *f;
14773         DIR     *d;
14774         char    tmp[80], tmp2[80], fname[80];
14775         unsigned int    acflag;
14776         struct dirent*  de;
14777
14778         f = fopen("/proc/apm", "r");
14779         if (f) {
14780                 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
14781                         acflag = 1;
14782                 fclose(f);
14783                 return (acflag != 1);
14784         }
14785         d = opendir("/proc/acpi/ac_adapter");
14786         if (d) {
14787                 while ((de=readdir(d)) != NULL) {
14788                         if (!strncmp(".", de->d_name, 1))
14789                                 continue;
14790                         snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
14791                                  de->d_name);
14792                         f = fopen(fname, "r");
14793                         if (!f)
14794                                 continue;
14795                         if (fscanf(f, "%s %s", tmp2, tmp) != 2)
14796                                 tmp[0] = 0;
14797                         fclose(f);
14798                         if (strncmp(tmp, "off-line", 8) == 0) {
14799                                 closedir(d);
14800                                 return 1;
14801                         }
14802                 }
14803                 closedir(d);
14804         }
14805         return 0;
14806 }
14807
14808 /*
14809  * This routine checks to see if a filesystem can be skipped; if so,
14810  * it will exit with EXIT_OK.  Under some conditions it will print a
14811  * message explaining why a check is being forced.
14812  */
14813 static void check_if_skip(e2fsck_t ctx)
14814 {
14815         ext2_filsys fs = ctx->fs;
14816         const char *reason = NULL;
14817         unsigned int reason_arg = 0;
14818         long next_check;
14819         int batt = is_on_batt();
14820         time_t now = time(0);
14821
14822         if ((ctx->options & E2F_OPT_FORCE) || bad_blocks_file ||
14823             cflag || swapfs)
14824                 return;
14825
14826         if ((fs->super->s_state & EXT2_ERROR_FS) ||
14827             !ext2fs_test_valid(fs))
14828                 reason = _(" contains a file system with errors");
14829         else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
14830                 reason = _(" was not cleanly unmounted");
14831         else if ((fs->super->s_max_mnt_count > 0) &&
14832                  (fs->super->s_mnt_count >=
14833                   (unsigned) fs->super->s_max_mnt_count)) {
14834                 reason = _(" has been mounted %u times without being checked");
14835                 reason_arg = fs->super->s_mnt_count;
14836                 if (batt && (fs->super->s_mnt_count <
14837                              (unsigned) fs->super->s_max_mnt_count*2))
14838                         reason = 0;
14839         } else if (fs->super->s_checkinterval &&
14840                    ((now - fs->super->s_lastcheck) >=
14841                     fs->super->s_checkinterval)) {
14842                 reason = _(" has gone %u days without being checked");
14843                 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
14844                 if (batt && ((now - fs->super->s_lastcheck) <
14845                              fs->super->s_checkinterval*2))
14846                         reason = 0;
14847         }
14848         if (reason) {
14849                 fputs(ctx->device_name, stdout);
14850                 printf(reason, reason_arg);
14851                 fputs(_(", check forced.\n"), stdout);
14852                 return;
14853         }
14854         printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
14855                fs->super->s_inodes_count - fs->super->s_free_inodes_count,
14856                fs->super->s_inodes_count,
14857                fs->super->s_blocks_count - fs->super->s_free_blocks_count,
14858                fs->super->s_blocks_count);
14859         next_check = 100000;
14860         if (fs->super->s_max_mnt_count > 0) {
14861                 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
14862                 if (next_check <= 0)
14863                         next_check = 1;
14864         }
14865         if (fs->super->s_checkinterval &&
14866             ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
14867                 next_check = 1;
14868         if (next_check <= 5) {
14869                 if (next_check == 1)
14870                         fputs(_(" (check after next mount)"), stdout);
14871                 else
14872                         printf(_(" (check in %ld mounts)"), next_check);
14873         }
14874         fputc('\n', stdout);
14875         ext2fs_close(fs);
14876         ctx->fs = NULL;
14877         e2fsck_free_context(ctx);
14878         exit(EXIT_OK);
14879 }
14880
14881 /*
14882  * For completion notice
14883  */
14884 struct percent_tbl {
14885         int     max_pass;
14886         int     table[32];
14887 };
14888 static const struct percent_tbl e2fsck_tbl = {
14889         5, { 0, 70, 90, 92,  95, 100 }
14890 };
14891
14892 static char bar[128], spaces[128];
14893
14894 static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
14895                           int max)
14896 {
14897         float   percent;
14898
14899         if (pass <= 0)
14900                 return 0.0;
14901         if (pass > tbl->max_pass || max == 0)
14902                 return 100.0;
14903         percent = ((float) curr) / ((float) max);
14904         return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
14905                 + tbl->table[pass-1]);
14906 }
14907
14908 void e2fsck_clear_progbar(e2fsck_t ctx)
14909 {
14910         if (!(ctx->flags & E2F_FLAG_PROG_BAR))
14911                 return;
14912
14913         printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
14914                ctx->stop_meta);
14915         fflush(stdout);
14916         ctx->flags &= ~E2F_FLAG_PROG_BAR;
14917 }
14918
14919 int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
14920                            unsigned int dpynum)
14921 {
14922         static const char spinner[] = "\\|/-";
14923         int     i;
14924         unsigned int    tick;
14925         struct timeval  tv;
14926         int dpywidth;
14927         int fixed_percent;
14928
14929         if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
14930                 return 0;
14931
14932         /*
14933          * Calculate the new progress position.  If the
14934          * percentage hasn't changed, then we skip out right
14935          * away.
14936          */
14937         fixed_percent = (int) ((10 * percent) + 0.5);
14938         if (ctx->progress_last_percent == fixed_percent)
14939                 return 0;
14940         ctx->progress_last_percent = fixed_percent;
14941
14942         /*
14943          * If we've already updated the spinner once within
14944          * the last 1/8th of a second, no point doing it
14945          * again.
14946          */
14947         gettimeofday(&tv, NULL);
14948         tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
14949         if ((tick == ctx->progress_last_time) &&
14950             (fixed_percent != 0) && (fixed_percent != 1000))
14951                 return 0;
14952         ctx->progress_last_time = tick;
14953
14954         /*
14955          * Advance the spinner, and note that the progress bar
14956          * will be on the screen
14957          */
14958         ctx->progress_pos = (ctx->progress_pos+1) & 3;
14959         ctx->flags |= E2F_FLAG_PROG_BAR;
14960
14961         dpywidth = 66 - strlen(label);
14962         dpywidth = 8 * (dpywidth / 8);
14963         if (dpynum)
14964                 dpywidth -= 8;
14965
14966         i = ((percent * dpywidth) + 50) / 100;
14967         printf("%s%s: |%s%s", ctx->start_meta, label,
14968                bar + (sizeof(bar) - (i+1)),
14969                spaces + (sizeof(spaces) - (dpywidth - i + 1)));
14970         if (fixed_percent == 1000)
14971                 fputc('|', stdout);
14972         else
14973                 fputc(spinner[ctx->progress_pos & 3], stdout);
14974         printf(" %4.1f%%  ", percent);
14975         if (dpynum)
14976                 printf("%u\r", dpynum);
14977         else
14978                 fputs(" \r", stdout);
14979         fputs(ctx->stop_meta, stdout);
14980
14981         if (fixed_percent == 1000)
14982                 e2fsck_clear_progbar(ctx);
14983         fflush(stdout);
14984
14985         return 0;
14986 }
14987
14988 static int e2fsck_update_progress(e2fsck_t ctx, int pass,
14989                                   unsigned long cur, unsigned long max)
14990 {
14991         char buf[80];
14992         float percent;
14993
14994         if (pass == 0)
14995                 return 0;
14996
14997         if (ctx->progress_fd) {
14998                 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
14999                 write(ctx->progress_fd, buf, strlen(buf));
15000         } else {
15001                 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
15002                 e2fsck_simple_progress(ctx, ctx->device_name,
15003                                        percent, 0);
15004         }
15005         return 0;
15006 }
15007
15008 static void reserve_stdio_fds(void)
15009 {
15010         int     fd;
15011
15012         while (1) {
15013                 fd = open(bb_dev_null, O_RDWR);
15014                 if (fd > 2)
15015                         break;
15016                 if (fd < 0) {
15017                         fprintf(stderr, _("ERROR: Couldn't open "
15018                                 "/dev/null (%s)\n"),
15019                                 strerror(errno));
15020                         break;
15021                 }
15022         }
15023         close(fd);
15024 }
15025
15026 static void signal_progress_on(int sig FSCK_ATTR((unused)))
15027 {
15028         e2fsck_t ctx = e2fsck_global_ctx;
15029
15030         if (!ctx)
15031                 return;
15032
15033         ctx->progress = e2fsck_update_progress;
15034         ctx->progress_fd = 0;
15035 }
15036
15037 static void signal_progress_off(int sig FSCK_ATTR((unused)))
15038 {
15039         e2fsck_t ctx = e2fsck_global_ctx;
15040
15041         if (!ctx)
15042                 return;
15043
15044         e2fsck_clear_progbar(ctx);
15045         ctx->progress = 0;
15046 }
15047
15048 static void signal_cancel(int sig FSCK_ATTR((unused)))
15049 {
15050         e2fsck_t ctx = e2fsck_global_ctx;
15051
15052         if (!ctx)
15053                 exit(FSCK_CANCELED);
15054
15055         ctx->flags |= E2F_FLAG_CANCEL;
15056 }
15057
15058 static void parse_extended_opts(e2fsck_t ctx, const char *opts)
15059 {
15060         char    *buf, *token, *next, *p, *arg;
15061         int     ea_ver;
15062         int     extended_usage = 0;
15063
15064         buf = string_copy(opts, 0);
15065         for (token = buf; token && *token; token = next) {
15066                 p = strchr(token, ',');
15067                 next = 0;
15068                 if (p) {
15069                         *p = 0;
15070                         next = p+1;
15071                 }
15072                 arg = strchr(token, '=');
15073                 if (arg) {
15074                         *arg = 0;
15075                         arg++;
15076                 }
15077                 if (strcmp(token, "ea_ver") == 0) {
15078                         if (!arg) {
15079                                 extended_usage++;
15080                                 continue;
15081                         }
15082                         ea_ver = strtoul(arg, &p, 0);
15083                         if (*p ||
15084                             ((ea_ver != 1) && (ea_ver != 2))) {
15085                                 fprintf(stderr,
15086                                         _("Invalid EA version.\n"));
15087                                 extended_usage++;
15088                                 continue;
15089                         }
15090                         ctx->ext_attr_ver = ea_ver;
15091                 } else {
15092                         fprintf(stderr, _("Unknown extended option: %s\n"),
15093                                 token);
15094                         extended_usage++;
15095                 }
15096         }
15097         if (extended_usage) {
15098                 bb_error_msg_and_die(
15099                         "Extended options are separated by commas, "
15100                         "and may take an argument which\n"
15101                         "is set off by an equals ('=') sign.  "
15102                         "Valid extended options are:\n"
15103                         "\tea_ver=<ea_version (1 or 2)>\n\n");
15104         }
15105 }
15106
15107
15108 static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
15109 {
15110         int             flush = 0;
15111         int             c, fd;
15112 #ifdef MTRACE
15113         extern void     *mallwatch;
15114 #endif
15115         e2fsck_t        ctx;
15116         errcode_t       retval;
15117         struct sigaction        sa;
15118         char            *extended_opts = 0;
15119
15120         retval = e2fsck_allocate_context(&ctx);
15121         if (retval)
15122                 return retval;
15123
15124         *ret_ctx = ctx;
15125
15126         setvbuf(stdout, NULL, _IONBF, BUFSIZ);
15127         setvbuf(stderr, NULL, _IONBF, BUFSIZ);
15128         if (isatty(0) && isatty(1)) {
15129                 ctx->interactive = 1;
15130         } else {
15131                 ctx->start_meta[0] = '\001';
15132                 ctx->stop_meta[0] = '\002';
15133         }
15134         memset(bar, '=', sizeof(bar)-1);
15135         memset(spaces, ' ', sizeof(spaces)-1);
15136         blkid_get_cache(&ctx->blkid, NULL);
15137
15138         if (argc && *argv)
15139                 ctx->program_name = *argv;
15140         else
15141                 ctx->program_name = "e2fsck";
15142         while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
15143                 switch (c) {
15144                 case 'C':
15145                         ctx->progress = e2fsck_update_progress;
15146                         ctx->progress_fd = atoi(optarg);
15147                         if (!ctx->progress_fd)
15148                                 break;
15149                         /* Validate the file descriptor to avoid disasters */
15150                         fd = dup(ctx->progress_fd);
15151                         if (fd < 0) {
15152                                 fprintf(stderr,
15153                                 _("Error validating file descriptor %d: %s\n"),
15154                                         ctx->progress_fd,
15155                                         error_message(errno));
15156                                 fatal_error(ctx,
15157                         _("Invalid completion information file descriptor"));
15158                         } else
15159                                 close(fd);
15160                         break;
15161                 case 'D':
15162                         ctx->options |= E2F_OPT_COMPRESS_DIRS;
15163                         break;
15164                 case 'E':
15165                         extended_opts = optarg;
15166                         break;
15167                 case 'p':
15168                 case 'a':
15169                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
15170                         conflict_opt:
15171                                 fatal_error(ctx,
15172         _("Only one the options -p/-a, -n or -y may be specified."));
15173                         }
15174                         ctx->options |= E2F_OPT_PREEN;
15175                         break;
15176                 case 'n':
15177                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
15178                                 goto conflict_opt;
15179                         ctx->options |= E2F_OPT_NO;
15180                         break;
15181                 case 'y':
15182                         if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
15183                                 goto conflict_opt;
15184                         ctx->options |= E2F_OPT_YES;
15185                         break;
15186                 case 't':
15187 #ifdef RESOURCE_TRACK
15188                         if (ctx->options & E2F_OPT_TIME)
15189                                 ctx->options |= E2F_OPT_TIME2;
15190                         else
15191                                 ctx->options |= E2F_OPT_TIME;
15192 #else
15193                         fprintf(stderr, _("The -t option is not "
15194                                 "supported on this version of e2fsck.\n"));
15195 #endif
15196                         break;
15197                 case 'c':
15198                         if (cflag++)
15199                                 ctx->options |= E2F_OPT_WRITECHECK;
15200                         ctx->options |= E2F_OPT_CHECKBLOCKS;
15201                         break;
15202                 case 'r':
15203                         /* What we do by default, anyway! */
15204                         break;
15205                 case 'b':
15206                         ctx->use_superblock = atoi(optarg);
15207                         ctx->flags |= E2F_FLAG_SB_SPECIFIED;
15208                         break;
15209                 case 'B':
15210                         ctx->blocksize = atoi(optarg);
15211                         break;
15212                 case 'I':
15213                         ctx->inode_buffer_blocks = atoi(optarg);
15214                         break;
15215                 case 'j':
15216                         ctx->journal_name = string_copy(optarg, 0);
15217                         break;
15218                 case 'P':
15219                         ctx->process_inode_size = atoi(optarg);
15220                         break;
15221                 case 'L':
15222                         replace_bad_blocks++;
15223                 case 'l':
15224                         bad_blocks_file = string_copy(optarg, 0);
15225                         break;
15226                 case 'd':
15227                         ctx->options |= E2F_OPT_DEBUG;
15228                         break;
15229                 case 'f':
15230                         ctx->options |= E2F_OPT_FORCE;
15231                         break;
15232                 case 'F':
15233                         flush = 1;
15234                         break;
15235                 case 'v':
15236                         verbose = 1;
15237                         break;
15238                 case 'V':
15239                         show_version_only = 1;
15240                         break;
15241 #ifdef MTRACE
15242                 case 'M':
15243                         mallwatch = (void *) strtol(optarg, NULL, 0);
15244                         break;
15245 #endif
15246                 case 'N':
15247                         ctx->device_name = optarg;
15248                         break;
15249 #ifdef ENABLE_SWAPFS
15250                 case 's':
15251                         normalize_swapfs = 1;
15252                 case 'S':
15253                         swapfs = 1;
15254                         break;
15255 #else
15256                 case 's':
15257                 case 'S':
15258                         fprintf(stderr, _("Byte-swapping filesystems "
15259                                           "not compiled in this version "
15260                                           "of e2fsck\n"));
15261                         exit(1);
15262 #endif
15263                 case 'k':
15264                         keep_bad_blocks++;
15265                         break;
15266                 default:
15267                         usage();
15268                 }
15269         if (show_version_only)
15270                 return 0;
15271         if (optind != argc - 1)
15272                 usage();
15273         if ((ctx->options & E2F_OPT_NO) && !bad_blocks_file &&
15274             !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
15275                 ctx->options |= E2F_OPT_READONLY;
15276         ctx->io_options = strchr(argv[optind], '?');
15277         if (ctx->io_options)
15278                 *ctx->io_options++ = 0;
15279         ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
15280         if (!ctx->filesystem_name) {
15281                 com_err(ctx->program_name, 0, _("Unable to resolve '%s'"),
15282                         argv[optind]);
15283                 fatal_error(ctx, 0);
15284         }
15285         if (extended_opts)
15286                 parse_extended_opts(ctx, extended_opts);
15287
15288         if (flush) {
15289                 fd = open(ctx->filesystem_name, O_RDONLY, 0);
15290                 if (fd < 0) {
15291                         com_err("open", errno,
15292                                 _("while opening %s for flushing"),
15293                                 ctx->filesystem_name);
15294                         fatal_error(ctx, 0);
15295                 }
15296                 if ((retval = ext2fs_sync_device(fd, 1))) {
15297                         com_err("ext2fs_sync_device", retval,
15298                                 _("while trying to flush %s"),
15299                                 ctx->filesystem_name);
15300                         fatal_error(ctx, 0);
15301                 }
15302                 close(fd);
15303         }
15304 #ifdef ENABLE_SWAPFS
15305         if (swapfs) {
15306                 if (cflag || bad_blocks_file) {
15307                         fprintf(stderr, _("Incompatible options not "
15308                                           "allowed when byte-swapping.\n"));
15309                         exit(EXIT_USAGE);
15310                 }
15311         }
15312 #endif
15313         if (cflag && bad_blocks_file) {
15314                 fprintf(stderr, _("The -c and the -l/-L options may "
15315                                   "not be both used at the same time.\n"));
15316                 exit(EXIT_USAGE);
15317         }
15318         /*
15319          * Set up signal action
15320          */
15321         memset(&sa, 0, sizeof(struct sigaction));
15322         sa.sa_handler = signal_cancel;
15323         sigaction(SIGINT, &sa, 0);
15324         sigaction(SIGTERM, &sa, 0);
15325 #ifdef SA_RESTART
15326         sa.sa_flags = SA_RESTART;
15327 #endif
15328         e2fsck_global_ctx = ctx;
15329         sa.sa_handler = signal_progress_on;
15330         sigaction(SIGUSR1, &sa, 0);
15331         sa.sa_handler = signal_progress_off;
15332         sigaction(SIGUSR2, &sa, 0);
15333
15334         /* Update our PATH to include /sbin if we need to run badblocks  */
15335         if (cflag)
15336                 e2fs_set_sbin_path();
15337 #ifdef __CONFIG_JBD_DEBUG__E2FS
15338         if (getenv("E2FSCK_JBD_DEBUG"))
15339                 journal_enable_debug = atoi(getenv("E2FSCK_JBD_DEBUG"));
15340 #endif
15341         return 0;
15342 }
15343
15344 static const char my_ver_string[] = E2FSPROGS_VERSION;
15345 static const char my_ver_date[] = E2FSPROGS_DATE;
15346
15347 int e2fsck_main (int argc, char *argv[])
15348 {
15349         errcode_t       retval;
15350         int             exit_value = EXIT_OK;
15351         ext2_filsys     fs = 0;
15352         io_manager      io_ptr;
15353         struct ext2_super_block *sb;
15354         const char      *lib_ver_date;
15355         int             my_ver, lib_ver;
15356         e2fsck_t        ctx;
15357         struct problem_context pctx;
15358         int flags, run_result;
15359
15360         clear_problem_context(&pctx);
15361 #ifdef MTRACE
15362         mtrace();
15363 #endif
15364 #ifdef MCHECK
15365         mcheck(0);
15366 #endif
15367 #ifdef ENABLE_NLS
15368         setlocale(LC_MESSAGES, "");
15369         setlocale(LC_CTYPE, "");
15370         bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
15371         textdomain(NLS_CAT_NAME);
15372 #endif
15373         my_ver = ext2fs_parse_version_string(my_ver_string);
15374         lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
15375         if (my_ver > lib_ver) {
15376                 fprintf( stderr, _("Error: ext2fs library version "
15377                         "out of date!\n"));
15378                 show_version_only++;
15379         }
15380
15381         retval = PRS(argc, argv, &ctx);
15382         if (retval) {
15383                 com_err("e2fsck", retval,
15384                         _("while trying to initialize program"));
15385                 exit(EXIT_ERROR);
15386         }
15387         reserve_stdio_fds();
15388
15389 #ifdef RESOURCE_TRACK
15390         init_resource_track(&ctx->global_rtrack);
15391 #endif
15392
15393         if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
15394                 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
15395                          my_ver_date);
15396
15397         if (show_version_only) {
15398                 fprintf(stderr, _("\tUsing %s, %s\n"),
15399                         error_message(EXT2_ET_BASE), lib_ver_date);
15400                 exit(EXIT_OK);
15401         }
15402
15403         check_mount(ctx);
15404
15405         if (!(ctx->options & E2F_OPT_PREEN) &&
15406             !(ctx->options & E2F_OPT_NO) &&
15407             !(ctx->options & E2F_OPT_YES)) {
15408                 if (!ctx->interactive)
15409                         fatal_error(ctx,
15410                                     _("need terminal for interactive repairs"));
15411         }
15412         ctx->superblock = ctx->use_superblock;
15413 restart:
15414 #ifdef CONFIG_TESTIO_DEBUG
15415         io_ptr = test_io_manager;
15416         test_io_backing_manager = unix_io_manager;
15417 #else
15418         io_ptr = unix_io_manager;
15419 #endif
15420         flags = 0;
15421         if ((ctx->options & E2F_OPT_READONLY) == 0)
15422                 flags |= EXT2_FLAG_RW;
15423
15424         if (ctx->superblock && ctx->blocksize) {
15425                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
15426                                       flags, ctx->superblock, ctx->blocksize,
15427                                       io_ptr, &fs);
15428         } else if (ctx->superblock) {
15429                 int blocksize;
15430                 for (blocksize = EXT2_MIN_BLOCK_SIZE;
15431                      blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
15432                         retval = ext2fs_open2(ctx->filesystem_name,
15433                                               ctx->io_options, flags,
15434                                               ctx->superblock, blocksize,
15435                                               io_ptr, &fs);
15436                         if (!retval)
15437                                 break;
15438                 }
15439         } else
15440                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
15441                                       flags, 0, 0, io_ptr, &fs);
15442         if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
15443             !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
15444             ((retval == EXT2_ET_BAD_MAGIC) ||
15445              ((retval == 0) && ext2fs_check_desc(fs)))) {
15446                 if (!fs || (fs->group_desc_count > 1)) {
15447                         printf(_("%s trying backup blocks...\n"),
15448                                retval ? _("Couldn't find ext2 superblock,") :
15449                                _("Group descriptors look bad..."));
15450                         get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
15451                         if (fs)
15452                                 ext2fs_close(fs);
15453                         goto restart;
15454                 }
15455         }
15456         if (retval) {
15457                 com_err(ctx->program_name, retval, _("while trying to open %s"),
15458                         ctx->filesystem_name);
15459                 if (retval == EXT2_ET_REV_TOO_HIGH) {
15460                         printf(_("The filesystem revision is apparently "
15461                                "too high for this version of e2fsck.\n"
15462                                "(Or the filesystem superblock "
15463                                "is corrupt)\n\n"));
15464                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
15465                 } else if (retval == EXT2_ET_SHORT_READ)
15466                         printf(_("Could this be a zero-length partition?\n"));
15467                 else if ((retval == EPERM) || (retval == EACCES))
15468                         printf(_("You must have %s access to the "
15469                                "filesystem or be root\n"),
15470                                (ctx->options & E2F_OPT_READONLY) ?
15471                                "r/o" : "r/w");
15472                 else if (retval == ENXIO)
15473                         printf(_("Possibly non-existent or swap device?\n"));
15474 #ifdef EROFS
15475                 else if (retval == EROFS)
15476                         printf(_("Disk write-protected; use the -n option "
15477                                "to do a read-only\n"
15478                                "check of the device.\n"));
15479 #endif
15480                 else
15481                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
15482                 fatal_error(ctx, 0);
15483         }
15484         ctx->fs = fs;
15485         fs->priv_data = ctx;
15486         sb = fs->super;
15487         if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
15488                 com_err(ctx->program_name, EXT2_ET_REV_TOO_HIGH,
15489                         _("while trying to open %s"),
15490                         ctx->filesystem_name);
15491         get_newer:
15492                 fatal_error(ctx, _("Get a newer version of e2fsck!"));
15493         }
15494
15495         /*
15496          * Set the device name, which is used whenever we print error
15497          * or informational messages to the user.
15498          */
15499         if (ctx->device_name == 0 &&
15500             (sb->s_volume_name[0] != 0)) {
15501                 ctx->device_name = string_copy(sb->s_volume_name,
15502                                                sizeof(sb->s_volume_name));
15503         }
15504         if (ctx->device_name == 0)
15505                 ctx->device_name = ctx->filesystem_name;
15506
15507         /*
15508          * Make sure the ext3 superblock fields are consistent.
15509          */
15510         retval = e2fsck_check_ext3_journal(ctx);
15511         if (retval) {
15512                 com_err(ctx->program_name, retval,
15513                         _("while checking ext3 journal for %s"),
15514                         ctx->device_name);
15515                 fatal_error(ctx, 0);
15516         }
15517
15518         /*
15519          * Check to see if we need to do ext3-style recovery.  If so,
15520          * do it, and then restart the fsck.
15521          */
15522         if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
15523                 if (ctx->options & E2F_OPT_READONLY) {
15524                         printf(_("Warning: skipping journal recovery "
15525                                  "because doing a read-only filesystem "
15526                                  "check.\n"));
15527                         io_channel_flush(ctx->fs->io);
15528                 } else {
15529                         if (ctx->flags & E2F_FLAG_RESTARTED) {
15530                                 /*
15531                                  * Whoops, we attempted to run the
15532                                  * journal twice.  This should never
15533                                  * happen, unless the hardware or
15534                                  * device driver is being bogus.
15535                                  */
15536                                 com_err(ctx->program_name, 0,
15537                                         _("unable to set superblock flags on %s\n"), ctx->device_name);
15538                                 fatal_error(ctx, 0);
15539                         }
15540                         retval = e2fsck_run_ext3_journal(ctx);
15541                         if (retval) {
15542                                 com_err(ctx->program_name, retval,
15543                                 _("while recovering ext3 journal of %s"),
15544                                         ctx->device_name);
15545                                 fatal_error(ctx, 0);
15546                         }
15547                         ext2fs_close(ctx->fs);
15548                         ctx->fs = 0;
15549                         ctx->flags |= E2F_FLAG_RESTARTED;
15550                         goto restart;
15551                 }
15552         }
15553
15554         /*
15555          * Check for compatibility with the feature sets.  We need to
15556          * be more stringent than ext2fs_open().
15557          */
15558         if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
15559             (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
15560                 com_err(ctx->program_name, EXT2_ET_UNSUPP_FEATURE,
15561                         "(%s)", ctx->device_name);
15562                 goto get_newer;
15563         }
15564         if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
15565                 com_err(ctx->program_name, EXT2_ET_RO_UNSUPP_FEATURE,
15566                         "(%s)", ctx->device_name);
15567                 goto get_newer;
15568         }
15569 #ifdef ENABLE_COMPRESSION
15570         if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
15571                 com_err(ctx->program_name, 0,
15572                         _("Warning: compression support is experimental.\n"));
15573 #endif
15574 #ifndef ENABLE_HTREE
15575         if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
15576                 com_err(ctx->program_name, 0,
15577                         _("E2fsck not compiled with HTREE support,\n\t"
15578                           "but filesystem %s has HTREE directories.\n"),
15579                         ctx->device_name);
15580                 goto get_newer;
15581         }
15582 #endif
15583
15584         /*
15585          * If the user specified a specific superblock, presumably the
15586          * master superblock has been trashed.  So we mark the
15587          * superblock as dirty, so it can be written out.
15588          */
15589         if (ctx->superblock &&
15590             !(ctx->options & E2F_OPT_READONLY))
15591                 ext2fs_mark_super_dirty(fs);
15592
15593         /*
15594          * We only update the master superblock because (a) paranoia;
15595          * we don't want to corrupt the backup superblocks, and (b) we
15596          * don't need to update the mount count and last checked
15597          * fields in the backup superblock (the kernel doesn't
15598          * update the backup superblocks anyway).
15599          */
15600         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
15601
15602         ehandler_init(fs->io);
15603
15604         if (ctx->superblock)
15605                 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
15606         ext2fs_mark_valid(fs);
15607         check_super_block(ctx);
15608         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15609                 fatal_error(ctx, 0);
15610         check_if_skip(ctx);
15611         if (bad_blocks_file)
15612                 read_bad_blocks_file(ctx, bad_blocks_file, replace_bad_blocks);
15613         else if (cflag)
15614                 read_bad_blocks_file(ctx, 0, !keep_bad_blocks); /* Test disk */
15615         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15616                 fatal_error(ctx, 0);
15617 #ifdef ENABLE_SWAPFS
15618
15619 #ifdef WORDS_BIGENDIAN
15620 #define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
15621 #else
15622 #define NATIVE_FLAG 0
15623 #endif
15624
15625
15626         if (normalize_swapfs) {
15627                 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
15628                         fprintf(stderr, _("%s: Filesystem byte order "
15629                                 "already normalized.\n"), ctx->device_name);
15630                         fatal_error(ctx, 0);
15631                 }
15632         }
15633         if (swapfs) {
15634                 swap_filesys(ctx);
15635                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15636                         fatal_error(ctx, 0);
15637         }
15638 #endif
15639
15640         /*
15641          * Mark the system as valid, 'til proven otherwise
15642          */
15643         ext2fs_mark_valid(fs);
15644
15645         retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
15646         if (retval) {
15647                 com_err(ctx->program_name, retval,
15648                         _("while reading bad blocks inode"));
15649                 preenhalt(ctx);
15650                 printf(_("This doesn't bode well,"
15651                          " but we'll try to go on...\n"));
15652         }
15653
15654         run_result = e2fsck_run(ctx);
15655         e2fsck_clear_progbar(ctx);
15656         if (run_result == E2F_FLAG_RESTART) {
15657                 printf(_("Restarting e2fsck from the beginning...\n"));
15658                 retval = e2fsck_reset_context(ctx);
15659                 if (retval) {
15660                         com_err(ctx->program_name, retval,
15661                                 _("while resetting context"));
15662                         fatal_error(ctx, 0);
15663                 }
15664                 ext2fs_close(fs);
15665                 goto restart;
15666         }
15667         if (run_result & E2F_FLAG_CANCEL) {
15668                 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
15669                        ctx->device_name : ctx->filesystem_name);
15670                 exit_value |= FSCK_CANCELED;
15671         }
15672         if (run_result & E2F_FLAG_ABORT)
15673                 fatal_error(ctx, _("aborted"));
15674
15675 #ifdef MTRACE
15676         mtrace_print("Cleanup");
15677 #endif
15678         if (ext2fs_test_changed(fs)) {
15679                 exit_value |= EXIT_NONDESTRUCT;
15680                 if (!(ctx->options & E2F_OPT_PREEN))
15681                     printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
15682                                ctx->device_name);
15683                 if (ctx->mount_flags & EXT2_MF_ISROOT) {
15684                         printf(_("%s: ***** REBOOT LINUX *****\n"),
15685                                ctx->device_name);
15686                         exit_value |= EXIT_DESTRUCT;
15687                 }
15688         }
15689         if (!ext2fs_test_valid(fs)) {
15690                 printf(_("\n%s: ********** WARNING: Filesystem still has "
15691                          "errors **********\n\n"), ctx->device_name);
15692                 exit_value |= EXIT_UNCORRECTED;
15693                 exit_value &= ~EXIT_NONDESTRUCT;
15694         }
15695         if (exit_value & FSCK_CANCELED)
15696                 exit_value &= ~EXIT_NONDESTRUCT;
15697         else {
15698                 show_stats(ctx);
15699                 if (!(ctx->options & E2F_OPT_READONLY)) {
15700                         if (ext2fs_test_valid(fs)) {
15701                                 if (!(sb->s_state & EXT2_VALID_FS))
15702                                         exit_value |= EXIT_NONDESTRUCT;
15703                                 sb->s_state = EXT2_VALID_FS;
15704                         } else
15705                                 sb->s_state &= ~EXT2_VALID_FS;
15706                         sb->s_mnt_count = 0;
15707                         sb->s_lastcheck = time(NULL);
15708                         ext2fs_mark_super_dirty(fs);
15709                 }
15710         }
15711
15712         e2fsck_write_bitmaps(ctx);
15713
15714         ext2fs_close(fs);
15715         ctx->fs = NULL;
15716         free(ctx->filesystem_name);
15717         free(ctx->journal_name);
15718         e2fsck_free_context(ctx);
15719
15720 #ifdef RESOURCE_TRACK
15721         if (ctx->options & E2F_OPT_TIME)
15722                 print_resource_track(NULL, &ctx->global_rtrack);
15723 #endif
15724
15725         return exit_value;
15726 }