Once more, with fewer inappropriate semicolons.
[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         if (ctx->dir_info) {
2040                 ext2fs_free_mem(&ctx->dir_info);
2041                 ctx->dir_info = 0;
2042         }
2043         ctx->dir_info_size = 0;
2044         ctx->dir_info_count = 0;
2045 }
2046
2047 /*
2048  * Return the count of number of directories in the dir_info structure
2049  */
2050 static inline int e2fsck_get_num_dirinfo(e2fsck_t ctx)
2051 {
2052         return ctx->dir_info_count;
2053 }
2054
2055 /*
2056  * A simple interator function
2057  */
2058 static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
2059 {
2060         if (*control >= ctx->dir_info_count)
2061                 return 0;
2062
2063         return(ctx->dir_info + (*control)++);
2064 }
2065
2066 /*
2067  * dirinfo.c --- maintains the directory information table for e2fsck.
2068  *
2069  */
2070
2071 #ifdef ENABLE_HTREE
2072
2073 /*
2074  * This subroutine is called during pass1 to create a directory info
2075  * entry.  During pass1, the passed-in parent is 0; it will get filled
2076  * in during pass2.
2077  */
2078 static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
2079 {
2080         struct dx_dir_info *dir;
2081         int             i, j;
2082         errcode_t       retval;
2083         unsigned long   old_size;
2084
2085 #if 0
2086         printf("add_dx_dir_info for inode %lu...\n", ino);
2087 #endif
2088         if (!ctx->dx_dir_info) {
2089                 ctx->dx_dir_info_count = 0;
2090                 ctx->dx_dir_info_size = 100; /* Guess */
2091                 ctx->dx_dir_info  = (struct dx_dir_info *)
2092                         e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
2093                                                * sizeof (struct dx_dir_info),
2094                                                "directory map");
2095         }
2096
2097         if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
2098                 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
2099                 ctx->dx_dir_info_size += 10;
2100                 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
2101                                            sizeof(struct dx_dir_info),
2102                                            &ctx->dx_dir_info);
2103                 if (retval) {
2104                         ctx->dx_dir_info_size -= 10;
2105                         return;
2106                 }
2107         }
2108
2109         /*
2110          * Normally, add_dx_dir_info is called with each inode in
2111          * sequential order; but once in a while (like when pass 3
2112          * needs to recreate the root directory or lost+found
2113          * directory) it is called out of order.  In those cases, we
2114          * need to move the dx_dir_info entries down to make room, since
2115          * the dx_dir_info array needs to be sorted by inode number for
2116          * get_dx_dir_info()'s sake.
2117          */
2118         if (ctx->dx_dir_info_count &&
2119             ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
2120                 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
2121                         if (ctx->dx_dir_info[i-1].ino < ino)
2122                                 break;
2123                 dir = &ctx->dx_dir_info[i];
2124                 if (dir->ino != ino)
2125                         for (j = ctx->dx_dir_info_count++; j > i; j--)
2126                                 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
2127         } else
2128                 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
2129
2130         dir->ino = ino;
2131         dir->numblocks = num_blocks;
2132         dir->hashversion = 0;
2133         dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
2134                                        * sizeof (struct dx_dirblock_info),
2135                                        "dx_block info array");
2136
2137 }
2138
2139 /*
2140  * get_dx_dir_info() --- given an inode number, try to find the directory
2141  * information entry for it.
2142  */
2143 static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
2144 {
2145         int     low, high, mid;
2146
2147         low = 0;
2148         high = ctx->dx_dir_info_count-1;
2149         if (!ctx->dx_dir_info)
2150                 return 0;
2151         if (ino == ctx->dx_dir_info[low].ino)
2152                 return &ctx->dx_dir_info[low];
2153         if  (ino == ctx->dx_dir_info[high].ino)
2154                 return &ctx->dx_dir_info[high];
2155
2156         while (low < high) {
2157                 mid = (low+high)/2;
2158                 if (mid == low || mid == high)
2159                         break;
2160                 if (ino == ctx->dx_dir_info[mid].ino)
2161                         return &ctx->dx_dir_info[mid];
2162                 if (ino < ctx->dx_dir_info[mid].ino)
2163                         high = mid;
2164                 else
2165                         low = mid;
2166         }
2167         return 0;
2168 }
2169
2170 /*
2171  * Free the dx_dir_info structure when it isn't needed any more.
2172  */
2173 static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
2174 {
2175         int     i;
2176         struct dx_dir_info *dir;
2177
2178         if (ctx->dx_dir_info) {
2179                 dir = ctx->dx_dir_info;
2180                 for (i=0; i < ctx->dx_dir_info_count; i++) {
2181                         if (dir->dx_block) {
2182                                 ext2fs_free_mem(&dir->dx_block);
2183                                 dir->dx_block = 0;
2184                         }
2185                 }
2186                 ext2fs_free_mem(&ctx->dx_dir_info);
2187                 ctx->dx_dir_info = 0;
2188         }
2189         ctx->dx_dir_info_size = 0;
2190         ctx->dx_dir_info_count = 0;
2191 }
2192
2193 /*
2194  * A simple interator function
2195  */
2196 static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
2197 {
2198         if (*control >= ctx->dx_dir_info_count)
2199                 return 0;
2200
2201         return(ctx->dx_dir_info + (*control)++);
2202 }
2203
2204 #endif /* ENABLE_HTREE */
2205 /*
2206  * e2fsck.c - a consistency checker for the new extended file system.
2207  *
2208  */
2209
2210 /*
2211  * This function allocates an e2fsck context
2212  */
2213 static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
2214 {
2215         e2fsck_t        context;
2216         errcode_t       retval;
2217
2218         retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
2219         if (retval)
2220                 return retval;
2221
2222         memset(context, 0, sizeof(struct e2fsck_struct));
2223
2224         context->process_inode_size = 256;
2225         context->ext_attr_ver = 2;
2226
2227         *ret = context;
2228         return 0;
2229 }
2230
2231 struct ea_refcount_el {
2232         blk_t   ea_blk;
2233         int     ea_count;
2234 };
2235
2236 struct ea_refcount {
2237         blk_t           count;
2238         blk_t           size;
2239         blk_t           cursor;
2240         struct ea_refcount_el   *list;
2241 };
2242
2243 static void ea_refcount_free(ext2_refcount_t refcount)
2244 {
2245         if (!refcount)
2246                 return;
2247
2248         if (refcount->list)
2249                 ext2fs_free_mem(&refcount->list);
2250         ext2fs_free_mem(&refcount);
2251 }
2252
2253 /*
2254  * This function resets an e2fsck context; it is called when e2fsck
2255  * needs to be restarted.
2256  */
2257 static errcode_t e2fsck_reset_context(e2fsck_t ctx)
2258 {
2259         ctx->flags = 0;
2260         ctx->lost_and_found = 0;
2261         ctx->bad_lost_and_found = 0;
2262         if (ctx->inode_used_map) {
2263                 ext2fs_free_inode_bitmap(ctx->inode_used_map);
2264                 ctx->inode_used_map = 0;
2265         }
2266         if (ctx->inode_dir_map) {
2267                 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
2268                 ctx->inode_dir_map = 0;
2269         }
2270         if (ctx->inode_reg_map) {
2271                 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
2272                 ctx->inode_reg_map = 0;
2273         }
2274         if (ctx->block_found_map) {
2275                 ext2fs_free_block_bitmap(ctx->block_found_map);
2276                 ctx->block_found_map = 0;
2277         }
2278         if (ctx->inode_link_info) {
2279                 ext2fs_free_icount(ctx->inode_link_info);
2280                 ctx->inode_link_info = 0;
2281         }
2282         if (ctx->journal_io) {
2283                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
2284                         io_channel_close(ctx->journal_io);
2285                 ctx->journal_io = 0;
2286         }
2287         if (ctx->fs && ctx->fs->dblist) {
2288                 ext2fs_free_dblist(ctx->fs->dblist);
2289                 ctx->fs->dblist = 0;
2290         }
2291         e2fsck_free_dir_info(ctx);
2292 #ifdef ENABLE_HTREE
2293         e2fsck_free_dx_dir_info(ctx);
2294 #endif
2295         if (ctx->refcount) {
2296                 ea_refcount_free(ctx->refcount);
2297                 ctx->refcount = 0;
2298         }
2299         if (ctx->refcount_extra) {
2300                 ea_refcount_free(ctx->refcount_extra);
2301                 ctx->refcount_extra = 0;
2302         }
2303         if (ctx->block_dup_map) {
2304                 ext2fs_free_block_bitmap(ctx->block_dup_map);
2305                 ctx->block_dup_map = 0;
2306         }
2307         if (ctx->block_ea_map) {
2308                 ext2fs_free_block_bitmap(ctx->block_ea_map);
2309                 ctx->block_ea_map = 0;
2310         }
2311         if (ctx->inode_bb_map) {
2312                 ext2fs_free_inode_bitmap(ctx->inode_bb_map);
2313                 ctx->inode_bb_map = 0;
2314         }
2315         if (ctx->inode_bad_map) {
2316                 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
2317                 ctx->inode_bad_map = 0;
2318         }
2319         if (ctx->inode_imagic_map) {
2320                 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
2321                 ctx->inode_imagic_map = 0;
2322         }
2323         if (ctx->dirs_to_hash) {
2324                 ext2fs_u32_list_free(ctx->dirs_to_hash);
2325                 ctx->dirs_to_hash = 0;
2326         }
2327
2328         /*
2329          * Clear the array of invalid meta-data flags
2330          */
2331         if (ctx->invalid_inode_bitmap_flag) {
2332                 ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
2333                 ctx->invalid_inode_bitmap_flag = 0;
2334         }
2335         if (ctx->invalid_block_bitmap_flag) {
2336                 ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
2337                 ctx->invalid_block_bitmap_flag = 0;
2338         }
2339         if (ctx->invalid_inode_table_flag) {
2340                 ext2fs_free_mem(&ctx->invalid_inode_table_flag);
2341                 ctx->invalid_inode_table_flag = 0;
2342         }
2343
2344         /* Clear statistic counters */
2345         ctx->fs_directory_count = 0;
2346         ctx->fs_regular_count = 0;
2347         ctx->fs_blockdev_count = 0;
2348         ctx->fs_chardev_count = 0;
2349         ctx->fs_links_count = 0;
2350         ctx->fs_symlinks_count = 0;
2351         ctx->fs_fast_symlinks_count = 0;
2352         ctx->fs_fifo_count = 0;
2353         ctx->fs_total_count = 0;
2354         ctx->fs_badblocks_count = 0;
2355         ctx->fs_sockets_count = 0;
2356         ctx->fs_ind_count = 0;
2357         ctx->fs_dind_count = 0;
2358         ctx->fs_tind_count = 0;
2359         ctx->fs_fragmented = 0;
2360         ctx->large_files = 0;
2361
2362         /* Reset the superblock to the user's requested value */
2363         ctx->superblock = ctx->use_superblock;
2364
2365         return 0;
2366 }
2367
2368 static void e2fsck_free_context(e2fsck_t ctx)
2369 {
2370         if (!ctx)
2371                 return;
2372
2373         e2fsck_reset_context(ctx);
2374         if (ctx->blkid)
2375                 blkid_put_cache(ctx->blkid);
2376
2377         ext2fs_free_mem(&ctx);
2378 }
2379
2380 /*
2381  * ea_refcount.c
2382  */
2383
2384 /*
2385  * The strategy we use for keeping track of EA refcounts is as
2386  * follows.  We keep a sorted array of first EA blocks and its
2387  * reference counts.  Once the refcount has dropped to zero, it is
2388  * removed from the array to save memory space.  Once the EA block is
2389  * checked, its bit is set in the block_ea_map bitmap.
2390  */
2391
2392
2393 static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
2394 {
2395         ext2_refcount_t refcount;
2396         errcode_t       retval;
2397         size_t          bytes;
2398
2399         retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
2400         if (retval)
2401                 return retval;
2402         memset(refcount, 0, sizeof(struct ea_refcount));
2403
2404         if (!size)
2405                 size = 500;
2406         refcount->size = size;
2407         bytes = (size_t) (size * sizeof(struct ea_refcount_el));
2408 #ifdef DEBUG
2409         printf("Refcount allocated %d entries, %d bytes.\n",
2410                refcount->size, bytes);
2411 #endif
2412         retval = ext2fs_get_mem(bytes, &refcount->list);
2413         if (retval)
2414                 goto errout;
2415         memset(refcount->list, 0, bytes);
2416
2417         refcount->count = 0;
2418         refcount->cursor = 0;
2419
2420         *ret = refcount;
2421         return 0;
2422
2423 errout:
2424         ea_refcount_free(refcount);
2425         return(retval);
2426 }
2427
2428 /*
2429  * collapse_refcount() --- go through the refcount array, and get rid
2430  * of any count == zero entries
2431  */
2432 static void refcount_collapse(ext2_refcount_t refcount)
2433 {
2434         unsigned int    i, j;
2435         struct ea_refcount_el   *list;
2436
2437         list = refcount->list;
2438         for (i = 0, j = 0; i < refcount->count; i++) {
2439                 if (list[i].ea_count) {
2440                         if (i != j)
2441                                 list[j] = list[i];
2442                         j++;
2443                 }
2444         }
2445 #if defined(DEBUG) || defined(TEST_PROGRAM)
2446         printf("Refcount_collapse: size was %d, now %d\n",
2447                refcount->count, j);
2448 #endif
2449         refcount->count = j;
2450 }
2451
2452
2453 /*
2454  * insert_refcount_el() --- Insert a new entry into the sorted list at a
2455  *      specified position.
2456  */
2457 static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
2458                                                  blk_t blk, int pos)
2459 {
2460         struct ea_refcount_el   *el;
2461         errcode_t               retval;
2462         blk_t                   new_size = 0;
2463         int                     num;
2464
2465         if (refcount->count >= refcount->size) {
2466                 new_size = refcount->size + 100;
2467 #ifdef DEBUG
2468                 printf("Reallocating refcount %d entries...\n", new_size);
2469 #endif
2470                 retval = ext2fs_resize_mem((size_t) refcount->size *
2471                                            sizeof(struct ea_refcount_el),
2472                                            (size_t) new_size *
2473                                            sizeof(struct ea_refcount_el),
2474                                            &refcount->list);
2475                 if (retval)
2476                         return 0;
2477                 refcount->size = new_size;
2478         }
2479         num = (int) refcount->count - pos;
2480         if (num < 0)
2481                 return 0;       /* should never happen */
2482         if (num) {
2483                 memmove(&refcount->list[pos+1], &refcount->list[pos],
2484                         sizeof(struct ea_refcount_el) * num);
2485         }
2486         refcount->count++;
2487         el = &refcount->list[pos];
2488         el->ea_count = 0;
2489         el->ea_blk = blk;
2490         return el;
2491 }
2492
2493
2494 /*
2495  * get_refcount_el() --- given an block number, try to find refcount
2496  *      information in the sorted list.  If the create flag is set,
2497  *      and we can't find an entry, create one in the sorted list.
2498  */
2499 static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
2500                                               blk_t blk, int create)
2501 {
2502         float   range;
2503         int     low, high, mid;
2504         blk_t   lowval, highval;
2505
2506         if (!refcount || !refcount->list)
2507                 return 0;
2508 retry:
2509         low = 0;
2510         high = (int) refcount->count-1;
2511         if (create && ((refcount->count == 0) ||
2512                        (blk > refcount->list[high].ea_blk))) {
2513                 if (refcount->count >= refcount->size)
2514                         refcount_collapse(refcount);
2515
2516                 return insert_refcount_el(refcount, blk,
2517                                           (unsigned) refcount->count);
2518         }
2519         if (refcount->count == 0)
2520                 return 0;
2521
2522         if (refcount->cursor >= refcount->count)
2523                 refcount->cursor = 0;
2524         if (blk == refcount->list[refcount->cursor].ea_blk)
2525                 return &refcount->list[refcount->cursor++];
2526 #ifdef DEBUG
2527         printf("Non-cursor get_refcount_el: %u\n", blk);
2528 #endif
2529         while (low <= high) {
2530 #if 0
2531                 mid = (low+high)/2;
2532 #else
2533                 if (low == high)
2534                         mid = low;
2535                 else {
2536                         /* Interpolate for efficiency */
2537                         lowval = refcount->list[low].ea_blk;
2538                         highval = refcount->list[high].ea_blk;
2539
2540                         if (blk < lowval)
2541                                 range = 0;
2542                         else if (blk > highval)
2543                                 range = 1;
2544                         else
2545                                 range = ((float) (blk - lowval)) /
2546                                         (highval - lowval);
2547                         mid = low + ((int) (range * (high-low)));
2548                 }
2549 #endif
2550                 if (blk == refcount->list[mid].ea_blk) {
2551                         refcount->cursor = mid+1;
2552                         return &refcount->list[mid];
2553                 }
2554                 if (blk < refcount->list[mid].ea_blk)
2555                         high = mid-1;
2556                 else
2557                         low = mid+1;
2558         }
2559         /*
2560          * If we need to create a new entry, it should be right at
2561          * low (where high will be left at low-1).
2562          */
2563         if (create) {
2564                 if (refcount->count >= refcount->size) {
2565                         refcount_collapse(refcount);
2566                         if (refcount->count < refcount->size)
2567                                 goto retry;
2568                 }
2569                 return insert_refcount_el(refcount, blk, low);
2570         }
2571         return 0;
2572 }
2573
2574 static errcode_t
2575 ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
2576 {
2577         struct ea_refcount_el   *el;
2578
2579         el = get_refcount_el(refcount, blk, 1);
2580         if (!el)
2581                 return EXT2_ET_NO_MEMORY;
2582         el->ea_count++;
2583
2584         if (ret)
2585                 *ret = el->ea_count;
2586         return 0;
2587 }
2588
2589 static errcode_t
2590 ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
2591 {
2592         struct ea_refcount_el   *el;
2593
2594         el = get_refcount_el(refcount, blk, 0);
2595         if (!el || el->ea_count == 0)
2596                 return EXT2_ET_INVALID_ARGUMENT;
2597
2598         el->ea_count--;
2599
2600         if (ret)
2601                 *ret = el->ea_count;
2602         return 0;
2603 }
2604
2605 static errcode_t
2606 ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
2607 {
2608         struct ea_refcount_el   *el;
2609
2610         /*
2611          * Get the refcount element
2612          */
2613         el = get_refcount_el(refcount, blk, count ? 1 : 0);
2614         if (!el)
2615                 return count ? EXT2_ET_NO_MEMORY : 0;
2616         el->ea_count = count;
2617         return 0;
2618 }
2619
2620 static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
2621 {
2622         refcount->cursor = 0;
2623 }
2624
2625
2626 static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
2627 {
2628         struct ea_refcount_el   *list;
2629
2630         while (1) {
2631                 if (refcount->cursor >= refcount->count)
2632                         return 0;
2633                 list = refcount->list;
2634                 if (list[refcount->cursor].ea_count) {
2635                         if (ret)
2636                                 *ret = list[refcount->cursor].ea_count;
2637                         return list[refcount->cursor++].ea_blk;
2638                 }
2639                 refcount->cursor++;
2640         }
2641 }
2642
2643
2644 /*
2645  * ehandler.c --- handle bad block errors which come up during the
2646  *      course of an e2fsck session.
2647  */
2648
2649
2650 static const char *operation;
2651
2652 static errcode_t
2653 e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
2654                          void *data, size_t size FSCK_ATTR((unused)),
2655                          int actual FSCK_ATTR((unused)), errcode_t error)
2656 {
2657         int     i;
2658         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 read, try reading 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 = (char *) data;
2671                 for (i=0; i < count; i++, p += channel->block_size, block++) {
2672                         error = io_channel_read_blk(channel, block,
2673                                                     1, p);
2674                         if (error)
2675                                 return error;
2676                 }
2677                 return 0;
2678         }
2679         if (operation)
2680                 printf(_("Error reading block %lu (%s) while %s.  "), block,
2681                        error_message(error), operation);
2682         else
2683                 printf(_("Error reading block %lu (%s).  "), block,
2684                        error_message(error));
2685         preenhalt(ctx);
2686         if (ask(ctx, _("Ignore error"), 1)) {
2687                 if (ask(ctx, _("Force rewrite"), 1))
2688                         io_channel_write_blk(channel, block, 1, data);
2689                 return 0;
2690         }
2691
2692         return error;
2693 }
2694
2695 static errcode_t
2696 e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
2697                         const void *data, size_t size FSCK_ATTR((unused)),
2698                         int actual FSCK_ATTR((unused)), errcode_t error)
2699 {
2700         int             i;
2701         const char      *p;
2702         ext2_filsys fs = (ext2_filsys) channel->app_data;
2703         e2fsck_t ctx;
2704
2705         ctx = (e2fsck_t) fs->priv_data;
2706
2707         /*
2708          * If more than one block was written, try writing each block
2709          * separately.  We could use the actual bytes read to figure
2710          * out where to start, but we don't bother.
2711          */
2712         if (count > 1) {
2713                 p = (const char *) data;
2714                 for (i=0; i < count; i++, p += channel->block_size, block++) {
2715                         error = io_channel_write_blk(channel, block,
2716                                                      1, p);
2717                         if (error)
2718                                 return error;
2719                 }
2720                 return 0;
2721         }
2722
2723         if (operation)
2724                 printf(_("Error writing block %lu (%s) while %s.  "), block,
2725                        error_message(error), operation);
2726         else
2727                 printf(_("Error writing block %lu (%s).  "), block,
2728                        error_message(error));
2729         preenhalt(ctx);
2730         if (ask(ctx, _("Ignore error"), 1))
2731                 return 0;
2732
2733         return error;
2734 }
2735
2736 static inline const char *ehandler_operation(const char *op)
2737 {
2738         const char *ret = operation;
2739
2740         operation = op;
2741         return ret;
2742 }
2743
2744 static void ehandler_init(io_channel channel)
2745 {
2746         channel->read_error = e2fsck_handle_read_error;
2747         channel->write_error = e2fsck_handle_write_error;
2748 }
2749
2750 /*
2751  * journal.c --- code for handling the "ext3" journal
2752  *
2753  * Copyright (C) 2000 Andreas Dilger
2754  * Copyright (C) 2000 Theodore Ts'o
2755  *
2756  * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
2757  * Copyright (C) 1999 Red Hat Software
2758  *
2759  * This file may be redistributed under the terms of the
2760  * GNU General Public License version 2 or at your discretion
2761  * any later version.
2762  */
2763
2764 #define MNT_FL (MS_MGC_VAL | MS_RDONLY)
2765
2766
2767 #ifdef __CONFIG_JBD_DEBUG__E2FS         /* Enabled by configure --enable-jfs-debug */
2768 static int bh_count = 0;
2769 #endif
2770
2771 /*
2772  * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
2773  * This creates a larger static binary, and a smaller binary using
2774  * shared libraries.  It's also probably slightly less CPU-efficient,
2775  * which is why it's not on by default.  But, it's a good way of
2776  * testing the functions in inode_io.c and fileio.c.
2777  */
2778 #undef USE_INODE_IO
2779
2780 /* Kernel compatibility functions for handling the journal.  These allow us
2781  * to use the recovery.c file virtually unchanged from the kernel, so we
2782  * don't have to do much to keep kernel and user recovery in sync.
2783  */
2784 static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
2785 {
2786 #ifdef USE_INODE_IO
2787         *phys = block;
2788         return 0;
2789 #else
2790         struct inode    *inode = journal->j_inode;
2791         errcode_t       retval;
2792         blk_t           pblk;
2793
2794         if (!inode) {
2795                 *phys = block;
2796                 return 0;
2797         }
2798
2799         retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
2800                             &inode->i_ext2, NULL, 0, block, &pblk);
2801         *phys = pblk;
2802         return (retval);
2803 #endif
2804 }
2805
2806 static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
2807 {
2808         struct buffer_head *bh;
2809
2810         bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
2811         if (!bh)
2812                 return NULL;
2813
2814         jfs_debug(4, "getblk for block %lu (%d bytes)(total %d)\n",
2815                   (unsigned long) blocknr, blocksize, ++bh_count);
2816
2817         bh->b_ctx = kdev->k_ctx;
2818         if (kdev->k_dev == K_DEV_FS)
2819                 bh->b_io = kdev->k_ctx->fs->io;
2820         else
2821                 bh->b_io = kdev->k_ctx->journal_io;
2822         bh->b_size = blocksize;
2823         bh->b_blocknr = blocknr;
2824
2825         return bh;
2826 }
2827
2828 static void sync_blockdev(kdev_t kdev)
2829 {
2830         io_channel      io;
2831
2832         if (kdev->k_dev == K_DEV_FS)
2833                 io = kdev->k_ctx->fs->io;
2834         else
2835                 io = kdev->k_ctx->journal_io;
2836
2837         io_channel_flush(io);
2838 }
2839
2840 static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
2841 {
2842         int retval;
2843         struct buffer_head *bh;
2844
2845         for (; nr > 0; --nr) {
2846                 bh = *bhp++;
2847                 if (rw == READ && !bh->b_uptodate) {
2848                         jfs_debug(3, "reading block %lu/%p\n",
2849                                   (unsigned long) bh->b_blocknr, (void *) bh);
2850                         retval = io_channel_read_blk(bh->b_io,
2851                                                      bh->b_blocknr,
2852                                                      1, bh->b_data);
2853                         if (retval) {
2854                                 com_err(bh->b_ctx->device_name, retval,
2855                                         "while reading block %lu\n",
2856                                         (unsigned long) bh->b_blocknr);
2857                                 bh->b_err = retval;
2858                                 continue;
2859                         }
2860                         bh->b_uptodate = 1;
2861                 } else if (rw == WRITE && bh->b_dirty) {
2862                         jfs_debug(3, "writing block %lu/%p\n",
2863                                   (unsigned long) bh->b_blocknr, (void *) bh);
2864                         retval = io_channel_write_blk(bh->b_io,
2865                                                       bh->b_blocknr,
2866                                                       1, bh->b_data);
2867                         if (retval) {
2868                                 com_err(bh->b_ctx->device_name, retval,
2869                                         "while writing block %lu\n",
2870                                         (unsigned long) bh->b_blocknr);
2871                                 bh->b_err = retval;
2872                                 continue;
2873                         }
2874                         bh->b_dirty = 0;
2875                         bh->b_uptodate = 1;
2876                 } else {
2877                         jfs_debug(3, "no-op %s for block %lu\n",
2878                                   rw == READ ? "read" : "write",
2879                                   (unsigned long) bh->b_blocknr);
2880                 }
2881         }
2882 }
2883
2884 static inline void mark_buffer_dirty(struct buffer_head *bh)
2885 {
2886         bh->b_dirty = 1;
2887 }
2888
2889 static inline void mark_buffer_clean(struct buffer_head * bh)
2890 {
2891         bh->b_dirty = 0;
2892 }
2893
2894 static void brelse(struct buffer_head *bh)
2895 {
2896         if (bh->b_dirty)
2897                 ll_rw_block(WRITE, 1, &bh);
2898         jfs_debug(3, "freeing block %lu/%p (total %d)\n",
2899                   (unsigned long) bh->b_blocknr, (void *) bh, --bh_count);
2900         ext2fs_free_mem(&bh);
2901 }
2902
2903 static inline int buffer_uptodate(struct buffer_head *bh)
2904 {
2905         return bh->b_uptodate;
2906 }
2907
2908 static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
2909 {
2910         bh->b_uptodate = val;
2911 }
2912
2913 static void wait_on_buffer(struct buffer_head *bh)
2914 {
2915         if (!bh->b_uptodate)
2916                 ll_rw_block(READ, 1, &bh);
2917 }
2918
2919
2920 static void e2fsck_clear_recover(e2fsck_t ctx, int error)
2921 {
2922         ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
2923
2924         /* if we had an error doing journal recovery, we need a full fsck */
2925         if (error)
2926                 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
2927         ext2fs_mark_super_dirty(ctx->fs);
2928 }
2929
2930 static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
2931 {
2932         struct ext2_super_block *sb = ctx->fs->super;
2933         struct ext2_super_block jsuper;
2934         struct problem_context  pctx;
2935         struct buffer_head      *bh;
2936         struct inode            *j_inode = NULL;
2937         struct kdev_s           *dev_fs = NULL, *dev_journal;
2938         const char              *journal_name = 0;
2939         journal_t               *journal = NULL;
2940         errcode_t               retval = 0;
2941         io_manager              io_ptr = 0;
2942         unsigned long           start = 0;
2943         blk_t                   blk;
2944         int                     ext_journal = 0;
2945         int                     tried_backup_jnl = 0;
2946         int                     i;
2947
2948         clear_problem_context(&pctx);
2949
2950         journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
2951         if (!journal) {
2952                 return EXT2_ET_NO_MEMORY;
2953         }
2954
2955         dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
2956         if (!dev_fs) {
2957                 retval = EXT2_ET_NO_MEMORY;
2958                 goto errout;
2959         }
2960         dev_journal = dev_fs+1;
2961
2962         dev_fs->k_ctx = dev_journal->k_ctx = ctx;
2963         dev_fs->k_dev = K_DEV_FS;
2964         dev_journal->k_dev = K_DEV_JOURNAL;
2965
2966         journal->j_dev = dev_journal;
2967         journal->j_fs_dev = dev_fs;
2968         journal->j_inode = NULL;
2969         journal->j_blocksize = ctx->fs->blocksize;
2970
2971         if (uuid_is_null(sb->s_journal_uuid)) {
2972                 if (!sb->s_journal_inum)
2973                         return EXT2_ET_BAD_INODE_NUM;
2974                 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
2975                                                  "journal inode");
2976                 if (!j_inode) {
2977                         retval = EXT2_ET_NO_MEMORY;
2978                         goto errout;
2979                 }
2980
2981                 j_inode->i_ctx = ctx;
2982                 j_inode->i_ino = sb->s_journal_inum;
2983
2984                 if ((retval = ext2fs_read_inode(ctx->fs,
2985                                                 sb->s_journal_inum,
2986                                                 &j_inode->i_ext2))) {
2987                 try_backup_journal:
2988                         if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
2989                             tried_backup_jnl)
2990                                 goto errout;
2991                         memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
2992                         memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
2993                                EXT2_N_BLOCKS*4);
2994                         j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
2995                         j_inode->i_ext2.i_links_count = 1;
2996                         j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
2997                         tried_backup_jnl++;
2998                 }
2999                 if (!j_inode->i_ext2.i_links_count ||
3000                     !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
3001                         retval = EXT2_ET_NO_JOURNAL;
3002                         goto try_backup_journal;
3003                 }
3004                 if (j_inode->i_ext2.i_size / journal->j_blocksize <
3005                     JFS_MIN_JOURNAL_BLOCKS) {
3006                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
3007                         goto try_backup_journal;
3008                 }
3009                 for (i=0; i < EXT2_N_BLOCKS; i++) {
3010                         blk = j_inode->i_ext2.i_block[i];
3011                         if (!blk) {
3012                                 if (i < EXT2_NDIR_BLOCKS) {
3013                                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
3014                                         goto try_backup_journal;
3015                                 }
3016                                 continue;
3017                         }
3018                         if (blk < sb->s_first_data_block ||
3019                             blk >= sb->s_blocks_count) {
3020                                 retval = EXT2_ET_BAD_BLOCK_NUM;
3021                                 goto try_backup_journal;
3022                         }
3023                 }
3024                 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
3025
3026 #ifdef USE_INODE_IO
3027                 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
3028                                                  &j_inode->i_ext2,
3029                                                  &journal_name);
3030                 if (retval)
3031                         goto errout;
3032
3033                 io_ptr = inode_io_manager;
3034 #else
3035                 journal->j_inode = j_inode;
3036                 ctx->journal_io = ctx->fs->io;
3037                 if ((retval = journal_bmap(journal, 0, &start)) != 0)
3038                         goto errout;
3039 #endif
3040         } else {
3041                 ext_journal = 1;
3042                 if (!ctx->journal_name) {
3043                         char uuid[37];
3044
3045                         uuid_unparse(sb->s_journal_uuid, uuid);
3046                         ctx->journal_name = blkid_get_devname(ctx->blkid,
3047                                                               "UUID", uuid);
3048                         if (!ctx->journal_name)
3049                                 ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
3050                 }
3051                 journal_name = ctx->journal_name;
3052
3053                 if (!journal_name) {
3054                         fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
3055                         return EXT2_ET_LOAD_EXT_JOURNAL;
3056                 }
3057
3058                 jfs_debug(1, "Using journal file %s\n", journal_name);
3059                 io_ptr = unix_io_manager;
3060         }
3061
3062 #if 0
3063         test_io_backing_manager = io_ptr;
3064         io_ptr = test_io_manager;
3065 #endif
3066 #ifndef USE_INODE_IO
3067         if (ext_journal)
3068 #endif
3069                 retval = io_ptr->open(journal_name, IO_FLAG_RW,
3070                                       &ctx->journal_io);
3071         if (retval)
3072                 goto errout;
3073
3074         io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
3075
3076         if (ext_journal) {
3077                 if (ctx->fs->blocksize == 1024)
3078                         start = 1;
3079                 bh = getblk(dev_journal, start, ctx->fs->blocksize);
3080                 if (!bh) {
3081                         retval = EXT2_ET_NO_MEMORY;
3082                         goto errout;
3083                 }
3084                 ll_rw_block(READ, 1, &bh);
3085                 if ((retval = bh->b_err) != 0)
3086                         goto errout;
3087                 memcpy(&jsuper, start ? bh->b_data :  bh->b_data + 1024,
3088                        sizeof(jsuper));
3089                 brelse(bh);
3090 #ifdef EXT2FS_ENABLE_SWAPFS
3091                 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
3092                         ext2fs_swap_super(&jsuper);
3093 #endif
3094                 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
3095                     !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
3096                         fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
3097                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
3098                         goto errout;
3099                 }
3100                 /* Make sure the journal UUID is correct */
3101                 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
3102                            sizeof(jsuper.s_uuid))) {
3103                         fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
3104                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
3105                         goto errout;
3106                 }
3107
3108                 journal->j_maxlen = jsuper.s_blocks_count;
3109                 start++;
3110         }
3111
3112         if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
3113                 retval = EXT2_ET_NO_MEMORY;
3114                 goto errout;
3115         }
3116
3117         journal->j_sb_buffer = bh;
3118         journal->j_superblock = (journal_superblock_t *)bh->b_data;
3119
3120 #ifdef USE_INODE_IO
3121         if (j_inode)
3122                 ext2fs_free_mem(&j_inode);
3123 #endif
3124
3125         *ret_journal = journal;
3126         return 0;
3127
3128 errout:
3129         if (dev_fs)
3130                 ext2fs_free_mem(&dev_fs);
3131         if (j_inode)
3132                 ext2fs_free_mem(&j_inode);
3133         if (journal)
3134                 ext2fs_free_mem(&journal);
3135         return retval;
3136
3137 }
3138
3139 static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
3140                                               struct problem_context *pctx)
3141 {
3142         struct ext2_super_block *sb = ctx->fs->super;
3143         int recover = ctx->fs->super->s_feature_incompat &
3144                 EXT3_FEATURE_INCOMPAT_RECOVER;
3145         int has_journal = ctx->fs->super->s_feature_compat &
3146                 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
3147
3148         if (has_journal || sb->s_journal_inum) {
3149                 /* The journal inode is bogus, remove and force full fsck */
3150                 pctx->ino = sb->s_journal_inum;
3151                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
3152                         if (has_journal && sb->s_journal_inum)
3153                                 printf("*** ext3 journal has been deleted - "
3154                                        "filesystem is now ext2 only ***\n\n");
3155                         sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
3156                         sb->s_journal_inum = 0;
3157                         ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
3158                         e2fsck_clear_recover(ctx, 1);
3159                         return 0;
3160                 }
3161                 return EXT2_ET_BAD_INODE_NUM;
3162         } else if (recover) {
3163                 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
3164                         e2fsck_clear_recover(ctx, 1);
3165                         return 0;
3166                 }
3167                 return EXT2_ET_UNSUPP_FEATURE;
3168         }
3169         return 0;
3170 }
3171
3172 #define V1_SB_SIZE      0x0024
3173 static void clear_v2_journal_fields(journal_t *journal)
3174 {
3175         e2fsck_t ctx = journal->j_dev->k_ctx;
3176         struct problem_context pctx;
3177
3178         clear_problem_context(&pctx);
3179
3180         if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
3181                 return;
3182
3183         memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
3184                ctx->fs->blocksize-V1_SB_SIZE);
3185         mark_buffer_dirty(journal->j_sb_buffer);
3186 }
3187
3188
3189 static errcode_t e2fsck_journal_load(journal_t *journal)
3190 {
3191         e2fsck_t ctx = journal->j_dev->k_ctx;
3192         journal_superblock_t *jsb;
3193         struct buffer_head *jbh = journal->j_sb_buffer;
3194         struct problem_context pctx;
3195
3196         clear_problem_context(&pctx);
3197
3198         ll_rw_block(READ, 1, &jbh);
3199         if (jbh->b_err) {
3200                 com_err(ctx->device_name, jbh->b_err,
3201                         _("reading journal superblock\n"));
3202                 return jbh->b_err;
3203         }
3204
3205         jsb = journal->j_superblock;
3206         /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
3207         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
3208                 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
3209
3210         switch (ntohl(jsb->s_header.h_blocktype)) {
3211         case JFS_SUPERBLOCK_V1:
3212                 journal->j_format_version = 1;
3213                 if (jsb->s_feature_compat ||
3214                     jsb->s_feature_incompat ||
3215                     jsb->s_feature_ro_compat ||
3216                     jsb->s_nr_users)
3217                         clear_v2_journal_fields(journal);
3218                 break;
3219
3220         case JFS_SUPERBLOCK_V2:
3221                 journal->j_format_version = 2;
3222                 if (ntohl(jsb->s_nr_users) > 1 &&
3223                     uuid_is_null(ctx->fs->super->s_journal_uuid))
3224                         clear_v2_journal_fields(journal);
3225                 if (ntohl(jsb->s_nr_users) > 1) {
3226                         fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
3227                         return EXT2_ET_JOURNAL_UNSUPP_VERSION;
3228                 }
3229                 break;
3230
3231         /*
3232          * These should never appear in a journal super block, so if
3233          * they do, the journal is badly corrupted.
3234          */
3235         case JFS_DESCRIPTOR_BLOCK:
3236         case JFS_COMMIT_BLOCK:
3237         case JFS_REVOKE_BLOCK:
3238                 return EXT2_ET_CORRUPT_SUPERBLOCK;
3239
3240         /* If we don't understand the superblock major type, but there
3241          * is a magic number, then it is likely to be a new format we
3242          * just don't understand, so leave it alone. */
3243         default:
3244                 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
3245         }
3246
3247         if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
3248                 return EXT2_ET_UNSUPP_FEATURE;
3249
3250         if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
3251                 return EXT2_ET_RO_UNSUPP_FEATURE;
3252
3253         /* We have now checked whether we know enough about the journal
3254          * format to be able to proceed safely, so any other checks that
3255          * fail we should attempt to recover from. */
3256         if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
3257                 com_err(ctx->program_name, EXT2_ET_CORRUPT_SUPERBLOCK,
3258                         _("%s: no valid journal superblock found\n"),
3259                         ctx->device_name);
3260                 return EXT2_ET_CORRUPT_SUPERBLOCK;
3261         }
3262
3263         if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
3264                 journal->j_maxlen = ntohl(jsb->s_maxlen);
3265         else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
3266                 com_err(ctx->program_name, EXT2_ET_CORRUPT_SUPERBLOCK,
3267                         _("%s: journal too short\n"),
3268                         ctx->device_name);
3269                 return EXT2_ET_CORRUPT_SUPERBLOCK;
3270         }
3271
3272         journal->j_tail_sequence = ntohl(jsb->s_sequence);
3273         journal->j_transaction_sequence = journal->j_tail_sequence;
3274         journal->j_tail = ntohl(jsb->s_start);
3275         journal->j_first = ntohl(jsb->s_first);
3276         journal->j_last = ntohl(jsb->s_maxlen);
3277
3278         return 0;
3279 }
3280
3281 static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
3282                                        journal_t *journal)
3283 {
3284         char *p;
3285         union {
3286                 uuid_t uuid;
3287                 __u32 val[4];
3288         } u;
3289         __u32 new_seq = 0;
3290         int i;
3291
3292         /* Leave a valid existing V1 superblock signature alone.
3293          * Anything unrecognisable we overwrite with a new V2
3294          * signature. */
3295
3296         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
3297             jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
3298                 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
3299                 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
3300         }
3301
3302         /* Zero out everything else beyond the superblock header */
3303
3304         p = ((char *) jsb) + sizeof(journal_header_t);
3305         memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
3306
3307         jsb->s_blocksize = htonl(ctx->fs->blocksize);
3308         jsb->s_maxlen = htonl(journal->j_maxlen);
3309         jsb->s_first = htonl(1);
3310
3311         /* Initialize the journal sequence number so that there is "no"
3312          * chance we will find old "valid" transactions in the journal.
3313          * This avoids the need to zero the whole journal (slow to do,
3314          * and risky when we are just recovering the filesystem).
3315          */
3316         uuid_generate(u.uuid);
3317         for (i = 0; i < 4; i ++)
3318                 new_seq ^= u.val[i];
3319         jsb->s_sequence = htonl(new_seq);
3320
3321         mark_buffer_dirty(journal->j_sb_buffer);
3322         ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
3323 }
3324
3325 static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
3326                                                   journal_t *journal,
3327                                                   struct problem_context *pctx)
3328 {
3329         struct ext2_super_block *sb = ctx->fs->super;
3330         int recover = ctx->fs->super->s_feature_incompat &
3331                 EXT3_FEATURE_INCOMPAT_RECOVER;
3332
3333         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
3334                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
3335                         e2fsck_journal_reset_super(ctx, journal->j_superblock,
3336                                                    journal);
3337                         journal->j_transaction_sequence = 1;
3338                         e2fsck_clear_recover(ctx, recover);
3339                         return 0;
3340                 }
3341                 return EXT2_ET_CORRUPT_SUPERBLOCK;
3342         } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
3343                 return EXT2_ET_CORRUPT_SUPERBLOCK;
3344
3345         return 0;
3346 }
3347
3348 static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
3349                                    int reset, int drop)
3350 {
3351         journal_superblock_t *jsb;
3352
3353         if (drop)
3354                 mark_buffer_clean(journal->j_sb_buffer);
3355         else if (!(ctx->options & E2F_OPT_READONLY)) {
3356                 jsb = journal->j_superblock;
3357                 jsb->s_sequence = htonl(journal->j_transaction_sequence);
3358                 if (reset)
3359                         jsb->s_start = 0; /* this marks the journal as empty */
3360                 mark_buffer_dirty(journal->j_sb_buffer);
3361         }
3362         brelse(journal->j_sb_buffer);
3363
3364         if (ctx->journal_io) {
3365                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
3366                         io_channel_close(ctx->journal_io);
3367                 ctx->journal_io = 0;
3368         }
3369
3370 #ifndef USE_INODE_IO
3371         if (journal->j_inode)
3372                 ext2fs_free_mem(&journal->j_inode);
3373 #endif
3374         if (journal->j_fs_dev)
3375                 ext2fs_free_mem(&journal->j_fs_dev);
3376         ext2fs_free_mem(&journal);
3377 }
3378
3379 /*
3380  * This function makes sure that the superblock fields regarding the
3381  * journal are consistent.
3382  */
3383 static int e2fsck_check_ext3_journal(e2fsck_t ctx)
3384 {
3385         struct ext2_super_block *sb = ctx->fs->super;
3386         journal_t *journal;
3387         int recover = ctx->fs->super->s_feature_incompat &
3388                 EXT3_FEATURE_INCOMPAT_RECOVER;
3389         struct problem_context pctx;
3390         problem_t problem;
3391         int reset = 0, force_fsck = 0;
3392         int retval;
3393
3394         /* If we don't have any journal features, don't do anything more */
3395         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
3396             !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
3397             uuid_is_null(sb->s_journal_uuid))
3398                 return 0;
3399
3400         clear_problem_context(&pctx);
3401         pctx.num = sb->s_journal_inum;
3402
3403         retval = e2fsck_get_journal(ctx, &journal);
3404         if (retval) {
3405                 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
3406                     (retval == EXT2_ET_BAD_BLOCK_NUM) ||
3407                     (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
3408                     (retval == EXT2_ET_NO_JOURNAL))
3409                         return e2fsck_journal_fix_bad_inode(ctx, &pctx);
3410                 return retval;
3411         }
3412
3413         retval = e2fsck_journal_load(journal);
3414         if (retval) {
3415                 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
3416                     ((retval == EXT2_ET_UNSUPP_FEATURE) &&
3417                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
3418                                   &pctx))) ||
3419                     ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
3420                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
3421                                   &pctx))) ||
3422                     ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
3423                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
3424                         retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
3425                                                                   &pctx);
3426                 e2fsck_journal_release(ctx, journal, 0, 1);
3427                 return retval;
3428         }
3429
3430         /*
3431          * We want to make the flags consistent here.  We will not leave with
3432          * needs_recovery set but has_journal clear.  We can't get in a loop
3433          * with -y, -n, or -p, only if a user isn't making up their mind.
3434          */
3435 no_has_journal:
3436         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
3437                 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
3438                 pctx.str = "inode";
3439                 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
3440                         if (recover &&
3441                             !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
3442                                 goto no_has_journal;
3443                         /*
3444                          * Need a full fsck if we are releasing a
3445                          * journal stored on a reserved inode.
3446                          */
3447                         force_fsck = recover ||
3448                                 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
3449                         /* Clear all of the journal fields */
3450                         sb->s_journal_inum = 0;
3451                         sb->s_journal_dev = 0;
3452                         memset(sb->s_journal_uuid, 0,
3453                                sizeof(sb->s_journal_uuid));
3454                         e2fsck_clear_recover(ctx, force_fsck);
3455                 } else if (!(ctx->options & E2F_OPT_READONLY)) {
3456                         sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
3457                         ext2fs_mark_super_dirty(ctx->fs);
3458                 }
3459         }
3460
3461         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
3462             !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
3463             journal->j_superblock->s_start != 0) {
3464                 /* Print status information */
3465                 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
3466                 if (ctx->superblock)
3467                         problem = PR_0_JOURNAL_RUN_DEFAULT;
3468                 else
3469                         problem = PR_0_JOURNAL_RUN;
3470                 if (fix_problem(ctx, problem, &pctx)) {
3471                         ctx->options |= E2F_OPT_FORCE;
3472                         sb->s_feature_incompat |=
3473                                 EXT3_FEATURE_INCOMPAT_RECOVER;
3474                         ext2fs_mark_super_dirty(ctx->fs);
3475                 } else if (fix_problem(ctx,
3476                                        PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
3477                         reset = 1;
3478                         sb->s_state &= ~EXT2_VALID_FS;
3479                         ext2fs_mark_super_dirty(ctx->fs);
3480                 }
3481                 /*
3482                  * If the user answers no to the above question, we
3483                  * ignore the fact that journal apparently has data;
3484                  * accidentally replaying over valid data would be far
3485                  * worse than skipping a questionable recovery.
3486                  *
3487                  * XXX should we abort with a fatal error here?  What
3488                  * will the ext3 kernel code do if a filesystem with
3489                  * !NEEDS_RECOVERY but with a non-zero
3490                  * journal->j_superblock->s_start is mounted?
3491                  */
3492         }
3493
3494         e2fsck_journal_release(ctx, journal, reset, 0);
3495         return retval;
3496 }
3497
3498 static errcode_t recover_ext3_journal(e2fsck_t ctx)
3499 {
3500         journal_t *journal;
3501         int retval;
3502
3503         journal_init_revoke_caches();
3504         retval = e2fsck_get_journal(ctx, &journal);
3505         if (retval)
3506                 return retval;
3507
3508         retval = e2fsck_journal_load(journal);
3509         if (retval)
3510                 goto errout;
3511
3512         retval = journal_init_revoke(journal, 1024);
3513         if (retval)
3514                 goto errout;
3515
3516         retval = -journal_recover(journal);
3517         if (retval)
3518                 goto errout;
3519
3520         if (journal->j_superblock->s_errno) {
3521                 ctx->fs->super->s_state |= EXT2_ERROR_FS;
3522                 ext2fs_mark_super_dirty(ctx->fs);
3523                 journal->j_superblock->s_errno = 0;
3524                 mark_buffer_dirty(journal->j_sb_buffer);
3525         }
3526
3527 errout:
3528         journal_destroy_revoke(journal);
3529         journal_destroy_revoke_caches();
3530         e2fsck_journal_release(ctx, journal, 1, 0);
3531         return retval;
3532 }
3533
3534 static int e2fsck_run_ext3_journal(e2fsck_t ctx)
3535 {
3536         io_manager io_ptr = ctx->fs->io->manager;
3537         int blocksize = ctx->fs->blocksize;
3538         errcode_t       retval, recover_retval;
3539
3540         printf(_("%s: recovering journal\n"), ctx->device_name);
3541         if (ctx->options & E2F_OPT_READONLY) {
3542                 printf(_("%s: won't do journal recovery while read-only\n"),
3543                        ctx->device_name);
3544                 return EXT2_ET_FILE_RO;
3545         }
3546
3547         if (ctx->fs->flags & EXT2_FLAG_DIRTY)
3548                 ext2fs_flush(ctx->fs);  /* Force out any modifications */
3549
3550         recover_retval = recover_ext3_journal(ctx);
3551
3552         /*
3553          * Reload the filesystem context to get up-to-date data from disk
3554          * because journal recovery will change the filesystem under us.
3555          */
3556         ext2fs_close(ctx->fs);
3557         retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
3558                              ctx->superblock, blocksize, io_ptr,
3559                              &ctx->fs);
3560
3561         if (retval) {
3562                 com_err(ctx->program_name, retval,
3563                         _("while trying to re-open %s"),
3564                         ctx->device_name);
3565                 fatal_error(ctx, 0);
3566         }
3567         ctx->fs->priv_data = ctx;
3568
3569         /* Set the superblock flags */
3570         e2fsck_clear_recover(ctx, recover_retval);
3571         return recover_retval;
3572 }
3573
3574 /*
3575  * This function will move the journal inode from a visible file in
3576  * the filesystem directory hierarchy to the reserved inode if necessary.
3577  */
3578 static const char * const journal_names[] = {
3579         ".journal", "journal", ".journal.dat", "journal.dat", 0 };
3580
3581 static void e2fsck_move_ext3_journal(e2fsck_t ctx)
3582 {
3583         struct ext2_super_block *sb = ctx->fs->super;
3584         struct problem_context  pctx;
3585         struct ext2_inode       inode;
3586         ext2_filsys             fs = ctx->fs;
3587         ext2_ino_t              ino;
3588         errcode_t               retval;
3589         const char * const *    cpp;
3590         int                     group, mount_flags;
3591
3592         clear_problem_context(&pctx);
3593
3594         /*
3595          * If the filesystem is opened read-only, or there is no
3596          * journal, then do nothing.
3597          */
3598         if ((ctx->options & E2F_OPT_READONLY) ||
3599             (sb->s_journal_inum == 0) ||
3600             !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
3601                 return;
3602
3603         /*
3604          * Read in the journal inode
3605          */
3606         if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
3607                 return;
3608
3609         /*
3610          * If it's necessary to backup the journal inode, do so.
3611          */
3612         if ((sb->s_jnl_backup_type == 0) ||
3613             ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
3614              memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
3615                 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
3616                         memcpy(sb->s_jnl_blocks, inode.i_block,
3617                                EXT2_N_BLOCKS*4);
3618                         sb->s_jnl_blocks[16] = inode.i_size;
3619                         sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
3620                         ext2fs_mark_super_dirty(fs);
3621                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
3622                 }
3623         }
3624
3625         /*
3626          * If the journal is already the hidden inode, then do nothing
3627          */
3628         if (sb->s_journal_inum == EXT2_JOURNAL_INO)
3629                 return;
3630
3631         /*
3632          * The journal inode had better have only one link and not be readable.
3633          */
3634         if (inode.i_links_count != 1)
3635                 return;
3636
3637         /*
3638          * If the filesystem is mounted, or we can't tell whether
3639          * or not it's mounted, do nothing.
3640          */
3641         retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
3642         if (retval || (mount_flags & EXT2_MF_MOUNTED))
3643                 return;
3644
3645         /*
3646          * If we can't find the name of the journal inode, then do
3647          * nothing.
3648          */
3649         for (cpp = journal_names; *cpp; cpp++) {
3650                 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
3651                                        strlen(*cpp), 0, &ino);
3652                 if ((retval == 0) && (ino == sb->s_journal_inum))
3653                         break;
3654         }
3655         if (*cpp == 0)
3656                 return;
3657
3658         /* We need the inode bitmap to be loaded */
3659         retval = ext2fs_read_bitmaps(fs);
3660         if (retval)
3661                 return;
3662
3663         pctx.str = *cpp;
3664         if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
3665                 return;
3666
3667         /*
3668          * OK, we've done all the checks, let's actually move the
3669          * journal inode.  Errors at this point mean we need to force
3670          * an ext2 filesystem check.
3671          */
3672         if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
3673                 goto err_out;
3674         if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
3675                 goto err_out;
3676         sb->s_journal_inum = EXT2_JOURNAL_INO;
3677         ext2fs_mark_super_dirty(fs);
3678         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
3679         inode.i_links_count = 0;
3680         inode.i_dtime = time(0);
3681         if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
3682                 goto err_out;
3683
3684         group = ext2fs_group_of_ino(fs, ino);
3685         ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
3686         ext2fs_mark_ib_dirty(fs);
3687         fs->group_desc[group].bg_free_inodes_count++;
3688         fs->super->s_free_inodes_count++;
3689         return;
3690
3691 err_out:
3692         pctx.errcode = retval;
3693         fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
3694         fs->super->s_state &= ~EXT2_VALID_FS;
3695         ext2fs_mark_super_dirty(fs);
3696         return;
3697 }
3698
3699 /*
3700  * message.c --- print e2fsck messages (with compression)
3701  *
3702  * print_e2fsck_message() prints a message to the user, using
3703  * compression techniques and expansions of abbreviations.
3704  *
3705  * The following % expansions are supported:
3706  *
3707  *      %b      <blk>                   block number
3708  *      %B      <blkcount>              integer
3709  *      %c      <blk2>                  block number
3710  *      %Di     <dirent>->ino           inode number
3711  *      %Dn     <dirent>->name          string
3712  *      %Dr     <dirent>->rec_len
3713  *      %Dl     <dirent>->name_len
3714  *      %Dt     <dirent>->filetype
3715  *      %d      <dir>                   inode number
3716  *      %g      <group>                 integer
3717  *      %i      <ino>                   inode number
3718  *      %Is     <inode> -> i_size
3719  *      %IS     <inode> -> i_extra_isize
3720  *      %Ib     <inode> -> i_blocks
3721  *      %Il     <inode> -> i_links_count
3722  *      %Im     <inode> -> i_mode
3723  *      %IM     <inode> -> i_mtime
3724  *      %IF     <inode> -> i_faddr
3725  *      %If     <inode> -> i_file_acl
3726  *      %Id     <inode> -> i_dir_acl
3727  *      %Iu     <inode> -> i_uid
3728  *      %Ig     <inode> -> i_gid
3729  *      %j      <ino2>                  inode number
3730  *      %m      <com_err error message>
3731  *      %N      <num>
3732  *      %p      ext2fs_get_pathname of directory <ino>
3733  *      %P      ext2fs_get_pathname of <dirent>->ino with <ino2> as
3734  *                      the containing directory.  (If dirent is NULL
3735  *                      then return the pathname of directory <ino2>)
3736  *      %q      ext2fs_get_pathname of directory <dir>
3737  *      %Q      ext2fs_get_pathname of directory <ino> with <dir> as
3738  *                      the containing directory.
3739  *      %s      <str>                   miscellaneous string
3740  *      %S      backup superblock
3741  *      %X      <num> hexadecimal format
3742  *
3743  * The following '@' expansions are supported:
3744  *
3745  *      @a      extended attribute
3746  *      @A      error allocating
3747  *      @b      block
3748  *      @B      bitmap
3749  *      @c      compress
3750  *      @C      conflicts with some other fs block
3751  *      @D      deleted
3752  *      @d      directory
3753  *      @e      entry
3754  *      @E      Entry '%Dn' in %p (%i)
3755  *      @f      filesystem
3756  *      @F      for @i %i (%Q) is
3757  *      @g      group
3758  *      @h      HTREE directory inode
3759  *      @i      inode
3760  *      @I      illegal
3761  *      @j      journal
3762  *      @l      lost+found
3763  *      @L      is a link
3764  *      @o      orphaned
3765  *      @p      problem in
3766  *      @r      root inode
3767  *      @s      should be
3768  *      @S      superblock
3769  *      @u      unattached
3770  *      @v      device
3771  *      @z      zero-length
3772  */
3773
3774
3775 /*
3776  * This structure defines the abbreviations used by the text strings
3777  * below.  The first character in the string is the index letter.  An
3778  * abbreviation of the form '@<i>' is expanded by looking up the index
3779  * letter <i> in the table below.
3780  */
3781 static const char * const abbrevs[] = {
3782         N_("aextended attribute"),
3783         N_("Aerror allocating"),
3784         N_("bblock"),
3785         N_("Bbitmap"),
3786         N_("ccompress"),
3787         N_("Cconflicts with some other fs @b"),
3788         N_("iinode"),
3789         N_("Iillegal"),
3790         N_("jjournal"),
3791         N_("Ddeleted"),
3792         N_("ddirectory"),
3793         N_("eentry"),
3794         N_("E@e '%Dn' in %p (%i)"),
3795         N_("ffilesystem"),
3796         N_("Ffor @i %i (%Q) is"),
3797         N_("ggroup"),
3798         N_("hHTREE @d @i"),
3799         N_("llost+found"),
3800         N_("Lis a link"),
3801         N_("oorphaned"),
3802         N_("pproblem in"),
3803         N_("rroot @i"),
3804         N_("sshould be"),
3805         N_("Ssuper@b"),
3806         N_("uunattached"),
3807         N_("vdevice"),
3808         N_("zzero-length"),
3809         "@@",
3810         0
3811         };
3812
3813 /*
3814  * Give more user friendly names to the "special" inodes.
3815  */
3816 #define num_special_inodes      11
3817 static const char * const special_inode_name[] =
3818 {
3819         N_("<The NULL inode>"),                 /* 0 */
3820         N_("<The bad blocks inode>"),           /* 1 */
3821         "/",                                    /* 2 */
3822         N_("<The ACL index inode>"),            /* 3 */
3823         N_("<The ACL data inode>"),             /* 4 */
3824         N_("<The boot loader inode>"),          /* 5 */
3825         N_("<The undelete directory inode>"),   /* 6 */
3826         N_("<The group descriptor inode>"),     /* 7 */
3827         N_("<The journal inode>"),              /* 8 */
3828         N_("<Reserved inode 9>"),               /* 9 */
3829         N_("<Reserved inode 10>"),              /* 10 */
3830 };
3831
3832 /*
3833  * This function does "safe" printing.  It will convert non-printable
3834  * ASCII characters using '^' and M- notation.
3835  */
3836 static void safe_print(const char *cp, int len)
3837 {
3838         unsigned char   ch;
3839
3840         if (len < 0)
3841                 len = strlen(cp);
3842
3843         while (len--) {
3844                 ch = *cp++;
3845                 if (ch > 128) {
3846                         fputs("M-", stdout);
3847                         ch -= 128;
3848                 }
3849                 if ((ch < 32) || (ch == 0x7f)) {
3850                         fputc('^', stdout);
3851                         ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
3852                 }
3853                 fputc(ch, stdout);
3854         }
3855 }
3856
3857
3858 /*
3859  * This function prints a pathname, using the ext2fs_get_pathname
3860  * function
3861  */
3862 static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
3863 {
3864         errcode_t       retval;
3865         char            *path;
3866
3867         if (!dir && (ino < num_special_inodes)) {
3868                 fputs(_(special_inode_name[ino]), stdout);
3869                 return;
3870         }
3871
3872         retval = ext2fs_get_pathname(fs, dir, ino, &path);
3873         if (retval)
3874                 fputs("???", stdout);
3875         else {
3876                 safe_print(path, -1);
3877                 ext2fs_free_mem(&path);
3878         }
3879 }
3880
3881 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
3882                           struct problem_context *pctx, int first);
3883 /*
3884  * This function handles the '@' expansion.  We allow recursive
3885  * expansion; an @ expression can contain further '@' and '%'
3886  * expressions.
3887  */
3888 static void expand_at_expression(e2fsck_t ctx, char ch,
3889                                           struct problem_context *pctx,
3890                                           int *first)
3891 {
3892         const char * const *cpp;
3893         const char *str;
3894
3895         /* Search for the abbreviation */
3896         for (cpp = abbrevs; *cpp; cpp++) {
3897                 if (ch == *cpp[0])
3898                         break;
3899         }
3900         if (*cpp) {
3901                 str = _(*cpp) + 1;
3902                 if (*first && islower(*str)) {
3903                         *first = 0;
3904                         fputc(toupper(*str++), stdout);
3905                 }
3906                 print_e2fsck_message(ctx, str, pctx, *first);
3907         } else
3908                 printf("@%c", ch);
3909 }
3910
3911 /*
3912  * This function expands '%IX' expressions
3913  */
3914 static void expand_inode_expression(char ch,
3915                                              struct problem_context *ctx)
3916 {
3917         struct ext2_inode       *inode;
3918         struct ext2_inode_large *large_inode;
3919         char *                  time_str;
3920         time_t                  t;
3921         int                     do_gmt = -1;
3922
3923         if (!ctx || !ctx->inode)
3924                 goto no_inode;
3925
3926         inode = ctx->inode;
3927         large_inode = (struct ext2_inode_large *) inode;
3928
3929         switch (ch) {
3930         case 's':
3931                 if (LINUX_S_ISDIR(inode->i_mode))
3932                         printf("%u", inode->i_size);
3933                 else {
3934 #ifdef EXT2_NO_64_TYPE
3935                         if (inode->i_size_high)
3936                                 printf("0x%x%08x", inode->i_size_high,
3937                                        inode->i_size);
3938                         else
3939                                 printf("%u", inode->i_size);
3940 #else
3941                         printf("%llu", (inode->i_size |
3942                                         ((__u64) inode->i_size_high << 32)));
3943 #endif
3944                 }
3945                 break;
3946         case 'S':
3947                 printf("%u", large_inode->i_extra_isize);
3948                 break;
3949         case 'b':
3950                 printf("%u", inode->i_blocks);
3951                 break;
3952         case 'l':
3953                 printf("%d", inode->i_links_count);
3954                 break;
3955         case 'm':
3956                 printf("0%o", inode->i_mode);
3957                 break;
3958         case 'M':
3959                 /* The diet libc doesn't respect the TZ environemnt variable */
3960                 if (do_gmt == -1) {
3961                         time_str = getenv("TZ");
3962                         if (!time_str)
3963                                 time_str = "";
3964                         do_gmt = !strcmp(time_str, "GMT");
3965                 }
3966                 t = inode->i_mtime;
3967                 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
3968                 printf("%.24s", time_str);
3969                 break;
3970         case 'F':
3971                 printf("%u", inode->i_faddr);
3972                 break;
3973         case 'f':
3974                 printf("%u", inode->i_file_acl);
3975                 break;
3976         case 'd':
3977                 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
3978                               inode->i_dir_acl : 0));
3979                 break;
3980         case 'u':
3981                 printf("%d", (inode->i_uid |
3982                               (inode->osd2.linux2.l_i_uid_high << 16)));
3983                 break;
3984         case 'g':
3985                 printf("%d", (inode->i_gid |
3986                               (inode->osd2.linux2.l_i_gid_high << 16)));
3987                 break;
3988         default:
3989         no_inode:
3990                 printf("%%I%c", ch);
3991                 break;
3992         }
3993 }
3994
3995 /*
3996  * This function expands '%dX' expressions
3997  */
3998 static _INLINE_ void expand_dirent_expression(char ch,
3999                                               struct problem_context *ctx)
4000 {
4001         struct ext2_dir_entry   *dirent;
4002         int     len;
4003
4004         if (!ctx || !ctx->dirent)
4005                 goto no_dirent;
4006
4007         dirent = ctx->dirent;
4008
4009         switch (ch) {
4010         case 'i':
4011                 printf("%u", dirent->inode);
4012                 break;
4013         case 'n':
4014                 len = dirent->name_len & 0xFF;
4015                 if (len > EXT2_NAME_LEN)
4016                         len = EXT2_NAME_LEN;
4017                 if (len > dirent->rec_len)
4018                         len = dirent->rec_len;
4019                 safe_print(dirent->name, len);
4020                 break;
4021         case 'r':
4022                 printf("%u", dirent->rec_len);
4023                 break;
4024         case 'l':
4025                 printf("%u", dirent->name_len & 0xFF);
4026                 break;
4027         case 't':
4028                 printf("%u", dirent->name_len >> 8);
4029                 break;
4030         default:
4031         no_dirent:
4032                 printf("%%D%c", ch);
4033                 break;
4034         }
4035 }
4036
4037 static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
4038                                                struct problem_context *ctx)
4039 {
4040         if (!ctx)
4041                 goto no_context;
4042
4043         switch (ch) {
4044         case '%':
4045                 fputc('%', stdout);
4046                 break;
4047         case 'b':
4048                 printf("%u", ctx->blk);
4049                 break;
4050         case 'B':
4051 #ifdef EXT2_NO_64_TYPE
4052                 printf("%d", ctx->blkcount);
4053 #else
4054                 printf("%lld", ctx->blkcount);
4055 #endif
4056                 break;
4057         case 'c':
4058                 printf("%u", ctx->blk2);
4059                 break;
4060         case 'd':
4061                 printf("%u", ctx->dir);
4062                 break;
4063         case 'g':
4064                 printf("%d", ctx->group);
4065                 break;
4066         case 'i':
4067                 printf("%u", ctx->ino);
4068                 break;
4069         case 'j':
4070                 printf("%u", ctx->ino2);
4071                 break;
4072         case 'm':
4073                 printf("%s", error_message(ctx->errcode));
4074                 break;
4075         case 'N':
4076 #ifdef EXT2_NO_64_TYPE
4077                 printf("%u", ctx->num);
4078 #else
4079                 printf("%llu", ctx->num);
4080 #endif
4081                 break;
4082         case 'p':
4083                 print_pathname(fs, ctx->ino, 0);
4084                 break;
4085         case 'P':
4086                 print_pathname(fs, ctx->ino2,
4087                                ctx->dirent ? ctx->dirent->inode : 0);
4088                 break;
4089         case 'q':
4090                 print_pathname(fs, ctx->dir, 0);
4091                 break;
4092         case 'Q':
4093                 print_pathname(fs, ctx->dir, ctx->ino);
4094                 break;
4095         case 'S':
4096                 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
4097                 break;
4098         case 's':
4099                 printf("%s", ctx->str ? ctx->str : "NULL");
4100                 break;
4101         case 'X':
4102 #ifdef EXT2_NO_64_TYPE
4103                 printf("0x%x", ctx->num);
4104 #else
4105                 printf("0x%llx", ctx->num);
4106 #endif
4107                 break;
4108         default:
4109         no_context:
4110                 printf("%%%c", ch);
4111                 break;
4112         }
4113 }
4114
4115
4116 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
4117                           struct problem_context *pctx, int first)
4118 {
4119         ext2_filsys fs = ctx->fs;
4120         const char *    cp;
4121         int             i;
4122
4123         e2fsck_clear_progbar(ctx);
4124         for (cp = msg; *cp; cp++) {
4125                 if (cp[0] == '@') {
4126                         cp++;
4127                         expand_at_expression(ctx, *cp, pctx, &first);
4128                 } else if (cp[0] == '%' && cp[1] == 'I') {
4129                         cp += 2;
4130                         expand_inode_expression(*cp, pctx);
4131                 } else if (cp[0] == '%' && cp[1] == 'D') {
4132                         cp += 2;
4133                         expand_dirent_expression(*cp, pctx);
4134                 } else if ((cp[0] == '%')) {
4135                         cp++;
4136                         expand_percent_expression(fs, *cp, pctx);
4137                 } else {
4138                         for (i=0; cp[i]; i++)
4139                                 if ((cp[i] == '@') || cp[i] == '%')
4140                                         break;
4141                         printf("%.*s", i, cp);
4142                         cp += i-1;
4143                 }
4144                 first = 0;
4145         }
4146 }
4147
4148
4149 /*
4150  * region.c --- code which manages allocations within a region.
4151  */
4152
4153 struct region_el {
4154         region_addr_t   start;
4155         region_addr_t   end;
4156         struct region_el *next;
4157 };
4158
4159 struct region_struct {
4160         region_addr_t   min;
4161         region_addr_t   max;
4162         struct region_el *allocated;
4163 };
4164
4165 static region_t region_create(region_addr_t min, region_addr_t max)
4166 {
4167         region_t        region;
4168
4169         region = malloc(sizeof(struct region_struct));
4170         if (!region)
4171                 return NULL;
4172         memset(region, 0, sizeof(struct region_struct));
4173         region->min = min;
4174         region->max = max;
4175         return region;
4176 }
4177
4178 static void region_free(region_t region)
4179 {
4180         struct region_el        *r, *next;
4181
4182         for (r = region->allocated; r; r = next) {
4183                 next = r->next;
4184                 free(r);
4185         }
4186         memset(region, 0, sizeof(struct region_struct));
4187         free(region);
4188 }
4189
4190 static int region_allocate(region_t region, region_addr_t start, int n)
4191 {
4192         struct region_el        *r, *new_region, *prev, *next;
4193         region_addr_t end;
4194
4195         end = start+n;
4196         if ((start < region->min) || (end > region->max))
4197                 return -1;
4198         if (n == 0)
4199                 return 1;
4200
4201         /*
4202          * Search through the linked list.  If we find that it
4203          * conflicts witih something that's already allocated, return
4204          * 1; if we can find an existing region which we can grow, do
4205          * so.  Otherwise, stop when we find the appropriate place
4206          * insert a new region element into the linked list.
4207          */
4208         for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
4209                 if (((start >= r->start) && (start < r->end)) ||
4210                     ((end > r->start) && (end <= r->end)) ||
4211                     ((start <= r->start) && (end >= r->end)))
4212                         return 1;
4213                 if (end == r->start) {
4214                         r->start = start;
4215                         return 0;
4216                 }
4217                 if (start == r->end) {
4218                         if ((next = r->next)) {
4219                                 if (end > next->start)
4220                                         return 1;
4221                                 if (end == next->start) {
4222                                         r->end = next->end;
4223                                         r->next = next->next;
4224                                         free(next);
4225                                         return 0;
4226                                 }
4227                         }
4228                         r->end = end;
4229                         return 0;
4230                 }
4231                 if (start < r->start)
4232                         break;
4233         }
4234         /*
4235          * Insert a new region element structure into the linked list
4236          */
4237         new_region = malloc(sizeof(struct region_el));
4238         if (!new_region)
4239                 return -1;
4240         new_region->start = start;
4241         new_region->end = start + n;
4242         new_region->next = r;
4243         if (prev)
4244                 prev->next = new_region;
4245         else
4246                 region->allocated = new_region;
4247         return 0;
4248 }
4249
4250 /*
4251  * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
4252  *
4253  * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
4254  * and applies the following tests to each inode:
4255  *
4256  *      - The mode field of the inode must be legal.
4257  *      - The size and block count fields of the inode are correct.
4258  *      - A data block must not be used by another inode
4259  *
4260  * Pass 1 also gathers the collects the following information:
4261  *
4262  *      - A bitmap of which inodes are in use.          (inode_used_map)
4263  *      - A bitmap of which inodes are directories.     (inode_dir_map)
4264  *      - A bitmap of which inodes are regular files.   (inode_reg_map)
4265  *      - A bitmap of which inodes have bad fields.     (inode_bad_map)
4266  *      - A bitmap of which inodes are in bad blocks.   (inode_bb_map)
4267  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
4268  *      - A bitmap of which blocks are in use.          (block_found_map)
4269  *      - A bitmap of which blocks are in use by two inodes     (block_dup_map)
4270  *      - The data blocks of the directory inodes.      (dir_map)
4271  *
4272  * Pass 1 is designed to stash away enough information so that the
4273  * other passes should not need to read in the inode information
4274  * during the normal course of a filesystem check.  (Althogh if an
4275  * inconsistency is detected, other passes may need to read in an
4276  * inode to fix it.)
4277  *
4278  * Note that pass 1B will be invoked if there are any duplicate blocks
4279  * found.
4280  */
4281
4282
4283 static int process_block(ext2_filsys fs, blk_t  *blocknr,
4284                          e2_blkcnt_t blockcnt, blk_t ref_blk,
4285                          int ref_offset, void *priv_data);
4286 static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
4287                              e2_blkcnt_t blockcnt, blk_t ref_blk,
4288                              int ref_offset, void *priv_data);
4289 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4290                          char *block_buf);
4291 static void mark_table_blocks(e2fsck_t ctx);
4292 static void alloc_bb_map(e2fsck_t ctx);
4293 static void alloc_imagic_map(e2fsck_t ctx);
4294 static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
4295 static void handle_fs_bad_blocks(e2fsck_t ctx);
4296 static void process_inodes(e2fsck_t ctx, char *block_buf);
4297 static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b);
4298 static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan,
4299                                   dgrp_t group, void * priv_data);
4300 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
4301                                     char *block_buf, int adjust_sign);
4302 /* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
4303
4304 static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
4305                                struct ext2_inode * inode, int bufsize,
4306                                const char *proc);
4307
4308 struct process_block_struct_1 {
4309         ext2_ino_t      ino;
4310         unsigned        is_dir:1, is_reg:1, clear:1, suppress:1,
4311                                 fragmented:1, compressed:1, bbcheck:1;
4312         blk_t           num_blocks;
4313         blk_t           max_blocks;
4314         e2_blkcnt_t     last_block;
4315         int             num_illegal_blocks;
4316         blk_t           previous_block;
4317         struct ext2_inode *inode;
4318         struct problem_context *pctx;
4319         ext2fs_block_bitmap fs_meta_blocks;
4320         e2fsck_t        ctx;
4321 };
4322
4323 struct process_inode_block {
4324         ext2_ino_t ino;
4325         struct ext2_inode inode;
4326 };
4327
4328 struct scan_callback_struct {
4329         e2fsck_t        ctx;
4330         char            *block_buf;
4331 };
4332
4333 /*
4334  * For the inodes to process list.
4335  */
4336 static struct process_inode_block *inodes_to_process;
4337 static int process_inode_count;
4338
4339 static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
4340                             EXT2_MIN_BLOCK_LOG_SIZE + 1];
4341
4342 /*
4343  * Free all memory allocated by pass1 in preparation for restarting
4344  * things.
4345  */
4346 static void unwind_pass1(void)
4347 {
4348         ext2fs_free_mem(&inodes_to_process);
4349         inodes_to_process = 0;
4350 }
4351
4352 /*
4353  * Check to make sure a device inode is real.  Returns 1 if the device
4354  * checks out, 0 if not.
4355  *
4356  * Note: this routine is now also used to check FIFO's and Sockets,
4357  * since they have the same requirement; the i_block fields should be
4358  * zero.
4359  */
4360 static int
4361 e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
4362 {
4363         int     i;
4364
4365         /*
4366          * If i_blocks is non-zero, or the index flag is set, then
4367          * this is a bogus device/fifo/socket
4368          */
4369         if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
4370             (inode->i_flags & EXT2_INDEX_FL))
4371                 return 0;
4372
4373         /*
4374          * We should be able to do the test below all the time, but
4375          * because the kernel doesn't forcibly clear the device
4376          * inode's additional i_block fields, there are some rare
4377          * occasions when a legitimate device inode will have non-zero
4378          * additional i_block fields.  So for now, we only complain
4379          * when the immutable flag is set, which should never happen
4380          * for devices.  (And that's when the problem is caused, since
4381          * you can't set or clear immutable flags for devices.)  Once
4382          * the kernel has been fixed we can change this...
4383          */
4384         if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
4385                 for (i=4; i < EXT2_N_BLOCKS; i++)
4386                         if (inode->i_block[i])
4387                                 return 0;
4388         }
4389         return 1;
4390 }
4391
4392 /*
4393  * Check to make sure a symlink inode is real.  Returns 1 if the symlink
4394  * checks out, 0 if not.
4395  */
4396 static int
4397 e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
4398 {
4399         unsigned int len;
4400         int i;
4401         blk_t   blocks;
4402
4403         if ((inode->i_size_high || inode->i_size == 0) ||
4404             (inode->i_flags & EXT2_INDEX_FL))
4405                 return 0;
4406
4407         blocks = ext2fs_inode_data_blocks(fs, inode);
4408         if (blocks) {
4409                 if ((inode->i_size >= fs->blocksize) ||
4410                     (blocks != fs->blocksize >> 9) ||
4411                     (inode->i_block[0] < fs->super->s_first_data_block) ||
4412                     (inode->i_block[0] >= fs->super->s_blocks_count))
4413                         return 0;
4414
4415                 for (i = 1; i < EXT2_N_BLOCKS; i++)
4416                         if (inode->i_block[i])
4417                                 return 0;
4418
4419                 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
4420                         return 0;
4421
4422                 len = strnlen(buf, fs->blocksize);
4423                 if (len == fs->blocksize)
4424                         return 0;
4425         } else {
4426                 if (inode->i_size >= sizeof(inode->i_block))
4427                         return 0;
4428
4429                 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
4430                 if (len == sizeof(inode->i_block))
4431                         return 0;
4432         }
4433         if (len != inode->i_size)
4434                 return 0;
4435         return 1;
4436 }
4437
4438 /*
4439  * If the immutable (or append-only) flag is set on the inode, offer
4440  * to clear it.
4441  */
4442 #define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
4443 static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
4444 {
4445         if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
4446                 return;
4447
4448         if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
4449                 return;
4450
4451         pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
4452         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
4453 }
4454
4455 /*
4456  * If device, fifo or socket, check size is zero -- if not offer to
4457  * clear it
4458  */
4459 static void check_size(e2fsck_t ctx, struct problem_context *pctx)
4460 {
4461         struct ext2_inode *inode = pctx->inode;
4462
4463         if ((inode->i_size == 0) && (inode->i_size_high == 0))
4464                 return;
4465
4466         if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
4467                 return;
4468
4469         inode->i_size = 0;
4470         inode->i_size_high = 0;
4471         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
4472 }
4473
4474 static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
4475 {
4476         struct ext2_super_block *sb = ctx->fs->super;
4477         struct ext2_inode_large *inode;
4478         struct ext2_ext_attr_entry *entry;
4479         char *start, *end;
4480         int storage_size, remain, offs;
4481         int problem = 0;
4482
4483         inode = (struct ext2_inode_large *) pctx->inode;
4484         storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
4485                 inode->i_extra_isize;
4486         start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
4487                 inode->i_extra_isize + sizeof(__u32);
4488         end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
4489         entry = (struct ext2_ext_attr_entry *) start;
4490
4491         /* scan all entry's headers first */
4492
4493         /* take finish entry 0UL into account */
4494         remain = storage_size - sizeof(__u32);
4495         offs = end - start;
4496
4497         while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
4498
4499                 /* header eats this space */
4500                 remain -= sizeof(struct ext2_ext_attr_entry);
4501
4502                 /* is attribute name valid? */
4503                 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
4504                         pctx->num = entry->e_name_len;
4505                         problem = PR_1_ATTR_NAME_LEN;
4506                         goto fix;
4507                 }
4508
4509                 /* attribute len eats this space */
4510                 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
4511
4512                 /* check value size */
4513                 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
4514                         pctx->num = entry->e_value_size;
4515                         problem = PR_1_ATTR_VALUE_SIZE;
4516                         goto fix;
4517                 }
4518
4519                 /* check value placement */
4520                 if (entry->e_value_offs +
4521                     EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
4522                         printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
4523                         pctx->num = entry->e_value_offs;
4524                         problem = PR_1_ATTR_VALUE_OFFSET;
4525                         goto fix;
4526                 }
4527
4528                 /* e_value_block must be 0 in inode's ea */
4529                 if (entry->e_value_block != 0) {
4530                         pctx->num = entry->e_value_block;
4531                         problem = PR_1_ATTR_VALUE_BLOCK;
4532                         goto fix;
4533                 }
4534
4535                 /* e_hash must be 0 in inode's ea */
4536                 if (entry->e_hash != 0) {
4537                         pctx->num = entry->e_hash;
4538                         problem = PR_1_ATTR_HASH;
4539                         goto fix;
4540                 }
4541
4542                 remain -= entry->e_value_size;
4543                 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
4544
4545                 entry = EXT2_EXT_ATTR_NEXT(entry);
4546         }
4547 fix:
4548         /*
4549          * it seems like a corruption. it's very unlikely we could repair
4550          * EA(s) in automatic fashion -bzzz
4551          */
4552 #if 0
4553         problem = PR_1_ATTR_HASH;
4554 #endif
4555         if (problem == 0 || !fix_problem(ctx, problem, pctx))
4556                 return;
4557
4558         /* simple remove all possible EA(s) */
4559         *((__u32 *)start) = 0UL;
4560         e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
4561                                 EXT2_INODE_SIZE(sb), "pass1");
4562 }
4563
4564 static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
4565 {
4566         struct ext2_super_block *sb = ctx->fs->super;
4567         struct ext2_inode_large *inode;
4568         __u32 *eamagic;
4569         int min, max;
4570
4571         inode = (struct ext2_inode_large *) pctx->inode;
4572         if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
4573                 /* this isn't large inode. so, nothing to check */
4574                 return;
4575         }
4576
4577 #if 0
4578         printf("inode #%u, i_extra_size %d\n", pctx->ino,
4579                         inode->i_extra_isize);
4580 #endif
4581         /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
4582         min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
4583         max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
4584         /*
4585          * For now we will allow i_extra_isize to be 0, but really
4586          * implementations should never allow i_extra_isize to be 0
4587          */
4588         if (inode->i_extra_isize &&
4589             (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
4590                 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
4591                         return;
4592                 inode->i_extra_isize = min;
4593                 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
4594                                         EXT2_INODE_SIZE(sb), "pass1");
4595                 return;
4596         }
4597
4598         eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
4599                         inode->i_extra_isize);
4600         if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
4601                 /* it seems inode has an extended attribute(s) in body */
4602                 check_ea_in_inode(ctx, pctx);
4603         }
4604 }
4605
4606 static void e2fsck_pass1(e2fsck_t ctx)
4607 {
4608         int     i;
4609         __u64   max_sizes;
4610         ext2_filsys fs = ctx->fs;
4611         ext2_ino_t      ino;
4612         struct ext2_inode *inode;
4613         ext2_inode_scan scan;
4614         char            *block_buf;
4615 #ifdef RESOURCE_TRACK
4616         struct resource_track   rtrack;
4617 #endif
4618         unsigned char   frag, fsize;
4619         struct          problem_context pctx;
4620         struct          scan_callback_struct scan_struct;
4621         struct ext2_super_block *sb = ctx->fs->super;
4622         int             imagic_fs;
4623         int             busted_fs_time = 0;
4624         int             inode_size;
4625
4626 #ifdef RESOURCE_TRACK
4627         init_resource_track(&rtrack);
4628 #endif
4629         clear_problem_context(&pctx);
4630
4631         if (!(ctx->options & E2F_OPT_PREEN))
4632                 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
4633
4634         if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4635             !(ctx->options & E2F_OPT_NO)) {
4636                 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
4637                         ctx->dirs_to_hash = 0;
4638         }
4639
4640 #ifdef MTRACE
4641         mtrace_print("Pass 1");
4642 #endif
4643
4644 #define EXT2_BPP(bits) (1ULL << ((bits) - 2))
4645
4646         for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
4647                 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
4648                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
4649                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
4650                 max_sizes = (max_sizes * (1UL << i)) - 1;
4651                 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
4652         }
4653 #undef EXT2_BPP
4654
4655         imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
4656
4657         /*
4658          * Allocate bitmaps structures
4659          */
4660         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
4661                                               &ctx->inode_used_map);
4662         if (pctx.errcode) {
4663                 pctx.num = 1;
4664                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4665                 ctx->flags |= E2F_FLAG_ABORT;
4666                 return;
4667         }
4668         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4669                                 _("directory inode map"), &ctx->inode_dir_map);
4670         if (pctx.errcode) {
4671                 pctx.num = 2;
4672                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4673                 ctx->flags |= E2F_FLAG_ABORT;
4674                 return;
4675         }
4676         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4677                         _("regular file inode map"), &ctx->inode_reg_map);
4678         if (pctx.errcode) {
4679                 pctx.num = 6;
4680                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4681                 ctx->flags |= E2F_FLAG_ABORT;
4682                 return;
4683         }
4684         pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
4685                                               &ctx->block_found_map);
4686         if (pctx.errcode) {
4687                 pctx.num = 1;
4688                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
4689                 ctx->flags |= E2F_FLAG_ABORT;
4690                 return;
4691         }
4692         pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
4693                                              &ctx->inode_link_info);
4694         if (pctx.errcode) {
4695                 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
4696                 ctx->flags |= E2F_FLAG_ABORT;
4697                 return;
4698         }
4699         inode_size = EXT2_INODE_SIZE(fs->super);
4700         inode = (struct ext2_inode *)
4701                 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
4702
4703         inodes_to_process = (struct process_inode_block *)
4704                 e2fsck_allocate_memory(ctx,
4705                                        (ctx->process_inode_size *
4706                                         sizeof(struct process_inode_block)),
4707                                        "array of inodes to process");
4708         process_inode_count = 0;
4709
4710         pctx.errcode = ext2fs_init_dblist(fs, 0);
4711         if (pctx.errcode) {
4712                 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
4713                 ctx->flags |= E2F_FLAG_ABORT;
4714                 return;
4715         }
4716
4717         /*
4718          * If the last orphan field is set, clear it, since the pass1
4719          * processing will automatically find and clear the orphans.
4720          * In the future, we may want to try using the last_orphan
4721          * linked list ourselves, but for now, we clear it so that the
4722          * ext3 mount code won't get confused.
4723          */
4724         if (!(ctx->options & E2F_OPT_READONLY)) {
4725                 if (fs->super->s_last_orphan) {
4726                         fs->super->s_last_orphan = 0;
4727                         ext2fs_mark_super_dirty(fs);
4728                 }
4729         }
4730
4731         mark_table_blocks(ctx);
4732         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
4733                                                     "block interate buffer");
4734         e2fsck_use_inode_shortcuts(ctx, 1);
4735         ehandler_operation(_("doing inode scan"));
4736         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4737                                               &scan);
4738         if (pctx.errcode) {
4739                 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
4740                 ctx->flags |= E2F_FLAG_ABORT;
4741                 return;
4742         }
4743         ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
4744         ctx->stashed_inode = inode;
4745         scan_struct.ctx = ctx;
4746         scan_struct.block_buf = block_buf;
4747         ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
4748         if (ctx->progress)
4749                 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
4750                         return;
4751         if (fs->super->s_wtime < fs->super->s_inodes_count)
4752                 busted_fs_time = 1;
4753
4754         while (1) {
4755                 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
4756                                                           inode, inode_size);
4757                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4758                         return;
4759                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
4760                         if (!ctx->inode_bb_map)
4761                                 alloc_bb_map(ctx);
4762                         ext2fs_mark_inode_bitmap(ctx->inode_bb_map, ino);
4763                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4764                         continue;
4765                 }
4766                 if (pctx.errcode) {
4767                         fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
4768                         ctx->flags |= E2F_FLAG_ABORT;
4769                         return;
4770                 }
4771                 if (!ino)
4772                         break;
4773                 pctx.ino = ino;
4774                 pctx.inode = inode;
4775                 ctx->stashed_ino = ino;
4776                 if (inode->i_links_count) {
4777                         pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
4778                                            ino, inode->i_links_count);
4779                         if (pctx.errcode) {
4780                                 pctx.num = inode->i_links_count;
4781                                 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
4782                                 ctx->flags |= E2F_FLAG_ABORT;
4783                                 return;
4784                         }
4785                 }
4786                 if (ino == EXT2_BAD_INO) {
4787                         struct process_block_struct_1 pb;
4788
4789                         pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
4790                                                           &pb.fs_meta_blocks);
4791                         if (pctx.errcode) {
4792                                 pctx.num = 4;
4793                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
4794                                 ctx->flags |= E2F_FLAG_ABORT;
4795                                 return;
4796                         }
4797                         pb.ino = EXT2_BAD_INO;
4798                         pb.num_blocks = pb.last_block = 0;
4799                         pb.num_illegal_blocks = 0;
4800                         pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
4801                         pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
4802                         pb.inode = inode;
4803                         pb.pctx = &pctx;
4804                         pb.ctx = ctx;
4805                         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
4806                                      block_buf, process_bad_block, &pb);
4807                         ext2fs_free_block_bitmap(pb.fs_meta_blocks);
4808                         if (pctx.errcode) {
4809                                 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
4810                                 ctx->flags |= E2F_FLAG_ABORT;
4811                                 return;
4812                         }
4813                         if (pb.bbcheck)
4814                                 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
4815                                 ctx->flags |= E2F_FLAG_ABORT;
4816                                 return;
4817                         }
4818                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4819                         clear_problem_context(&pctx);
4820                         continue;
4821                 } else if (ino == EXT2_ROOT_INO) {
4822                         /*
4823                          * Make sure the root inode is a directory; if
4824                          * not, offer to clear it.  It will be
4825                          * regnerated in pass #3.
4826                          */
4827                         if (!LINUX_S_ISDIR(inode->i_mode)) {
4828                                 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
4829                                         inode->i_dtime = time(0);
4830                                         inode->i_links_count = 0;
4831                                         ext2fs_icount_store(ctx->inode_link_info,
4832                                                             ino, 0);
4833                                         e2fsck_write_inode(ctx, ino, inode,
4834                                                            "pass1");
4835                                 }
4836
4837                         }
4838                         /*
4839                          * If dtime is set, offer to clear it.  mke2fs
4840                          * version 0.2b created filesystems with the
4841                          * dtime field set for the root and lost+found
4842                          * directories.  We won't worry about
4843                          * /lost+found, since that can be regenerated
4844                          * easily.  But we will fix the root directory
4845                          * as a special case.
4846                          */
4847                         if (inode->i_dtime && inode->i_links_count) {
4848                                 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
4849                                         inode->i_dtime = 0;
4850                                         e2fsck_write_inode(ctx, ino, inode,
4851                                                            "pass1");
4852                                 }
4853                         }
4854                 } else if (ino == EXT2_JOURNAL_INO) {
4855                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4856                         if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
4857                                 if (!LINUX_S_ISREG(inode->i_mode) &&
4858                                     fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
4859                                                 &pctx)) {
4860                                         inode->i_mode = LINUX_S_IFREG;
4861                                         e2fsck_write_inode(ctx, ino, inode,
4862                                                            "pass1");
4863                                 }
4864                                 check_blocks(ctx, &pctx, block_buf);
4865                                 continue;
4866                         }
4867                         if ((inode->i_links_count || inode->i_blocks ||
4868                              inode->i_blocks || inode->i_block[0]) &&
4869                             fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
4870                                         &pctx)) {
4871                                 memset(inode, 0, inode_size);
4872                                 ext2fs_icount_store(ctx->inode_link_info,
4873                                                     ino, 0);
4874                                 e2fsck_write_inode_full(ctx, ino, inode,
4875                                                         inode_size, "pass1");
4876                         }
4877                 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
4878                         int     problem = 0;
4879
4880                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4881                         if (ino == EXT2_BOOT_LOADER_INO) {
4882                                 if (LINUX_S_ISDIR(inode->i_mode))
4883                                         problem = PR_1_RESERVED_BAD_MODE;
4884                         } else if (ino == EXT2_RESIZE_INO) {
4885                                 if (inode->i_mode &&
4886                                     !LINUX_S_ISREG(inode->i_mode))
4887                                         problem = PR_1_RESERVED_BAD_MODE;
4888                         } else {
4889                                 if (inode->i_mode != 0)
4890                                         problem = PR_1_RESERVED_BAD_MODE;
4891                         }
4892                         if (problem) {
4893                                 if (fix_problem(ctx, problem, &pctx)) {
4894                                         inode->i_mode = 0;
4895                                         e2fsck_write_inode(ctx, ino, inode,
4896                                                            "pass1");
4897                                 }
4898                         }
4899                         check_blocks(ctx, &pctx, block_buf);
4900                         continue;
4901                 }
4902                 /*
4903                  * Check for inodes who might have been part of the
4904                  * orphaned list linked list.  They should have gotten
4905                  * dealt with by now, unless the list had somehow been
4906                  * corrupted.
4907                  *
4908                  * FIXME: In the future, inodes which are still in use
4909                  * (and which are therefore) pending truncation should
4910                  * be handled specially.  Right now we just clear the
4911                  * dtime field, and the normal e2fsck handling of
4912                  * inodes where i_size and the inode blocks are
4913                  * inconsistent is to fix i_size, instead of releasing
4914                  * the extra blocks.  This won't catch the inodes that
4915                  * was at the end of the orphan list, but it's better
4916                  * than nothing.  The right answer is that there
4917                  * shouldn't be any bugs in the orphan list handling.  :-)
4918                  */
4919                 if (inode->i_dtime && !busted_fs_time &&
4920                     inode->i_dtime < ctx->fs->super->s_inodes_count) {
4921                         if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
4922                                 inode->i_dtime = inode->i_links_count ?
4923                                         0 : time(0);
4924                                 e2fsck_write_inode(ctx, ino, inode,
4925                                                    "pass1");
4926                         }
4927                 }
4928
4929                 /*
4930                  * This code assumes that deleted inodes have
4931                  * i_links_count set to 0.
4932                  */
4933                 if (!inode->i_links_count) {
4934                         if (!inode->i_dtime && inode->i_mode) {
4935                                 if (fix_problem(ctx,
4936                                             PR_1_ZERO_DTIME, &pctx)) {
4937                                         inode->i_dtime = time(0);
4938                                         e2fsck_write_inode(ctx, ino, inode,
4939                                                            "pass1");
4940                                 }
4941                         }
4942                         continue;
4943                 }
4944                 /*
4945                  * n.b.  0.3c ext2fs code didn't clear i_links_count for
4946                  * deleted files.  Oops.
4947                  *
4948                  * Since all new ext2 implementations get this right,
4949                  * we now assume that the case of non-zero
4950                  * i_links_count and non-zero dtime means that we
4951                  * should keep the file, not delete it.
4952                  *
4953                  */
4954                 if (inode->i_dtime) {
4955                         if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
4956                                 inode->i_dtime = 0;
4957                                 e2fsck_write_inode(ctx, ino, inode, "pass1");
4958                         }
4959                 }
4960
4961                 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4962                 switch (fs->super->s_creator_os) {
4963                     case EXT2_OS_LINUX:
4964                         frag = inode->osd2.linux2.l_i_frag;
4965                         fsize = inode->osd2.linux2.l_i_fsize;
4966                         break;
4967                     case EXT2_OS_HURD:
4968                         frag = inode->osd2.hurd2.h_i_frag;
4969                         fsize = inode->osd2.hurd2.h_i_fsize;
4970                         break;
4971                     case EXT2_OS_MASIX:
4972                         frag = inode->osd2.masix2.m_i_frag;
4973                         fsize = inode->osd2.masix2.m_i_fsize;
4974                         break;
4975                     default:
4976                         frag = fsize = 0;
4977                 }
4978
4979                 if (inode->i_faddr || frag || fsize ||
4980                     (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
4981                         mark_inode_bad(ctx, ino);
4982                 if (inode->i_flags & EXT2_IMAGIC_FL) {
4983                         if (imagic_fs) {
4984                                 if (!ctx->inode_imagic_map)
4985                                         alloc_imagic_map(ctx);
4986                                 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
4987                                                          ino);
4988                         } else {
4989                                 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
4990                                         inode->i_flags &= ~EXT2_IMAGIC_FL;
4991                                         e2fsck_write_inode(ctx, ino,
4992                                                            inode, "pass1");
4993                                 }
4994                         }
4995                 }
4996
4997                 check_inode_extra_space(ctx, &pctx);
4998
4999                 if (LINUX_S_ISDIR(inode->i_mode)) {
5000                         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
5001                         e2fsck_add_dir_info(ctx, ino, 0);
5002                         ctx->fs_directory_count++;
5003                 } else if (LINUX_S_ISREG (inode->i_mode)) {
5004                         ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
5005                         ctx->fs_regular_count++;
5006                 } else if (LINUX_S_ISCHR (inode->i_mode) &&
5007                            e2fsck_pass1_check_device_inode(fs, inode)) {
5008                         check_immutable(ctx, &pctx);
5009                         check_size(ctx, &pctx);
5010                         ctx->fs_chardev_count++;
5011                 } else if (LINUX_S_ISBLK (inode->i_mode) &&
5012                            e2fsck_pass1_check_device_inode(fs, inode)) {
5013                         check_immutable(ctx, &pctx);
5014                         check_size(ctx, &pctx);
5015                         ctx->fs_blockdev_count++;
5016                 } else if (LINUX_S_ISLNK (inode->i_mode) &&
5017                            e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
5018                         check_immutable(ctx, &pctx);
5019                         ctx->fs_symlinks_count++;
5020                         if (ext2fs_inode_data_blocks(fs, inode) == 0) {
5021                                 ctx->fs_fast_symlinks_count++;
5022                                 check_blocks(ctx, &pctx, block_buf);
5023                                 continue;
5024                         }
5025                 }
5026                 else if (LINUX_S_ISFIFO (inode->i_mode) &&
5027                          e2fsck_pass1_check_device_inode(fs, inode)) {
5028                         check_immutable(ctx, &pctx);
5029                         check_size(ctx, &pctx);
5030                         ctx->fs_fifo_count++;
5031                 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
5032                            e2fsck_pass1_check_device_inode(fs, inode)) {
5033                         check_immutable(ctx, &pctx);
5034                         check_size(ctx, &pctx);
5035                         ctx->fs_sockets_count++;
5036                 } else
5037                         mark_inode_bad(ctx, ino);
5038                 if (inode->i_block[EXT2_IND_BLOCK])
5039                         ctx->fs_ind_count++;
5040                 if (inode->i_block[EXT2_DIND_BLOCK])
5041                         ctx->fs_dind_count++;
5042                 if (inode->i_block[EXT2_TIND_BLOCK])
5043                         ctx->fs_tind_count++;
5044                 if (inode->i_block[EXT2_IND_BLOCK] ||
5045                     inode->i_block[EXT2_DIND_BLOCK] ||
5046                     inode->i_block[EXT2_TIND_BLOCK] ||
5047                     inode->i_file_acl) {
5048                         inodes_to_process[process_inode_count].ino = ino;
5049                         inodes_to_process[process_inode_count].inode = *inode;
5050                         process_inode_count++;
5051                 } else
5052                         check_blocks(ctx, &pctx, block_buf);
5053
5054                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5055                         return;
5056
5057                 if (process_inode_count >= ctx->process_inode_size) {
5058                         process_inodes(ctx, block_buf);
5059
5060                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5061                                 return;
5062                 }
5063         }
5064         process_inodes(ctx, block_buf);
5065         ext2fs_close_inode_scan(scan);
5066         ehandler_operation(0);
5067
5068         /*
5069          * If any extended attribute blocks' reference counts need to
5070          * be adjusted, either up (ctx->refcount_extra), or down
5071          * (ctx->refcount), then fix them.
5072          */
5073         if (ctx->refcount) {
5074                 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
5075                 ea_refcount_free(ctx->refcount);
5076                 ctx->refcount = 0;
5077         }
5078         if (ctx->refcount_extra) {
5079                 adjust_extattr_refcount(ctx, ctx->refcount_extra,
5080                                         block_buf, +1);
5081                 ea_refcount_free(ctx->refcount_extra);
5082                 ctx->refcount_extra = 0;
5083         }
5084
5085         if (ctx->invalid_bitmaps)
5086                 handle_fs_bad_blocks(ctx);
5087
5088         /* We don't need the block_ea_map any more */
5089         if (ctx->block_ea_map) {
5090                 ext2fs_free_block_bitmap(ctx->block_ea_map);
5091                 ctx->block_ea_map = 0;
5092         }
5093
5094         if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
5095                 ext2fs_block_bitmap save_bmap;
5096
5097                 save_bmap = fs->block_map;
5098                 fs->block_map = ctx->block_found_map;
5099                 clear_problem_context(&pctx);
5100                 pctx.errcode = ext2fs_create_resize_inode(fs);
5101                 if (pctx.errcode) {
5102                         fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
5103                         /* Should never get here */
5104                         ctx->flags |= E2F_FLAG_ABORT;
5105                         return;
5106                 }
5107                 fs->block_map = save_bmap;
5108                 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
5109         }
5110
5111         if (ctx->flags & E2F_FLAG_RESTART) {
5112                 /*
5113                  * Only the master copy of the superblock and block
5114                  * group descriptors are going to be written during a
5115                  * restart, so set the superblock to be used to be the
5116                  * master superblock.
5117                  */
5118                 ctx->use_superblock = 0;
5119                 unwind_pass1();
5120                 goto endit;
5121         }
5122
5123         if (ctx->block_dup_map) {
5124                 if (ctx->options & E2F_OPT_PREEN) {
5125                         clear_problem_context(&pctx);
5126                         fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
5127                 }
5128                 e2fsck_pass1_dupblocks(ctx, block_buf);
5129         }
5130         ext2fs_free_mem(&inodes_to_process);
5131 endit:
5132         e2fsck_use_inode_shortcuts(ctx, 0);
5133
5134         ext2fs_free_mem(&block_buf);
5135         ext2fs_free_mem(&inode);
5136
5137 #ifdef RESOURCE_TRACK
5138         if (ctx->options & E2F_OPT_TIME2) {
5139                 e2fsck_clear_progbar(ctx);
5140                 print_resource_track(_("Pass 1"), &rtrack);
5141         }
5142 #endif
5143 }
5144
5145 /*
5146  * When the inode_scan routines call this callback at the end of the
5147  * glock group, call process_inodes.
5148  */
5149 static errcode_t scan_callback(ext2_filsys fs,
5150                                ext2_inode_scan scan FSCK_ATTR((unused)),
5151                                dgrp_t group, void * priv_data)
5152 {
5153         struct scan_callback_struct *scan_struct;
5154         e2fsck_t ctx;
5155
5156         scan_struct = (struct scan_callback_struct *) priv_data;
5157         ctx = scan_struct->ctx;
5158
5159         process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
5160
5161         if (ctx->progress)
5162                 if ((ctx->progress)(ctx, 1, group+1,
5163                                     ctx->fs->group_desc_count))
5164                         return EXT2_ET_CANCEL_REQUESTED;
5165
5166         return 0;
5167 }
5168
5169 /*
5170  * Process the inodes in the "inodes to process" list.
5171  */
5172 static void process_inodes(e2fsck_t ctx, char *block_buf)
5173 {
5174         int                     i;
5175         struct ext2_inode       *old_stashed_inode;
5176         ext2_ino_t              old_stashed_ino;
5177         const char              *old_operation;
5178         char                    buf[80];
5179         struct problem_context  pctx;
5180
5181 #if 0
5182         printf("begin process_inodes: ");
5183 #endif
5184         if (process_inode_count == 0)
5185                 return;
5186         old_operation = ehandler_operation(0);
5187         old_stashed_inode = ctx->stashed_inode;
5188         old_stashed_ino = ctx->stashed_ino;
5189         qsort(inodes_to_process, process_inode_count,
5190                       sizeof(struct process_inode_block), process_inode_cmp);
5191         clear_problem_context(&pctx);
5192         for (i=0; i < process_inode_count; i++) {
5193                 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
5194                 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
5195
5196 #if 0
5197                 printf("%u ", pctx.ino);
5198 #endif
5199                 sprintf(buf, _("reading indirect blocks of inode %u"),
5200                         pctx.ino);
5201                 ehandler_operation(buf);
5202                 check_blocks(ctx, &pctx, block_buf);
5203                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5204                         break;
5205         }
5206         ctx->stashed_inode = old_stashed_inode;
5207         ctx->stashed_ino = old_stashed_ino;
5208         process_inode_count = 0;
5209 #if 0
5210         printf("end process inodes\n");
5211 #endif
5212         ehandler_operation(old_operation);
5213 }
5214
5215 static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b)
5216 {
5217         const struct process_inode_block *ib_a =
5218                 (const struct process_inode_block *) a;
5219         const struct process_inode_block *ib_b =
5220                 (const struct process_inode_block *) b;
5221         int     ret;
5222
5223         ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
5224                ib_b->inode.i_block[EXT2_IND_BLOCK]);
5225         if (ret == 0)
5226                 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
5227         return ret;
5228 }
5229
5230 /*
5231  * Mark an inode as being bad in some what
5232  */
5233 static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
5234 {
5235         struct          problem_context pctx;
5236
5237         if (!ctx->inode_bad_map) {
5238                 clear_problem_context(&pctx);
5239
5240                 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
5241                             _("bad inode map"), &ctx->inode_bad_map);
5242                 if (pctx.errcode) {
5243                         pctx.num = 3;
5244                         fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
5245                         /* Should never get here */
5246                         ctx->flags |= E2F_FLAG_ABORT;
5247                         return;
5248                 }
5249         }
5250         ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
5251 }
5252
5253
5254 /*
5255  * This procedure will allocate the inode "bb" (badblock) map table
5256  */
5257 static void alloc_bb_map(e2fsck_t ctx)
5258 {
5259         struct          problem_context pctx;
5260
5261         clear_problem_context(&pctx);
5262         pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
5263                                               _("inode in bad block map"),
5264                                               &ctx->inode_bb_map);
5265         if (pctx.errcode) {
5266                 pctx.num = 4;
5267                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
5268                 /* Should never get here */
5269                 ctx->flags |= E2F_FLAG_ABORT;
5270                 return;
5271         }
5272 }
5273
5274 /*
5275  * This procedure will allocate the inode imagic table
5276  */
5277 static void alloc_imagic_map(e2fsck_t ctx)
5278 {
5279         struct          problem_context pctx;
5280
5281         clear_problem_context(&pctx);
5282         pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
5283                                               _("imagic inode map"),
5284                                               &ctx->inode_imagic_map);
5285         if (pctx.errcode) {
5286                 pctx.num = 5;
5287                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
5288                 /* Should never get here */
5289                 ctx->flags |= E2F_FLAG_ABORT;
5290                 return;
5291         }
5292 }
5293
5294 /*
5295  * Marks a block as in use, setting the dup_map if it's been set
5296  * already.  Called by process_block and process_bad_block.
5297  *
5298  * WARNING: Assumes checks have already been done to make sure block
5299  * is valid.  This is true in both process_block and process_bad_block.
5300  */
5301 static _INLINE_ void mark_block_used(e2fsck_t ctx, blk_t block)
5302 {
5303         struct          problem_context pctx;
5304
5305         clear_problem_context(&pctx);
5306
5307         if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
5308                 if (!ctx->block_dup_map) {
5309                         pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
5310                               _("multiply claimed block map"),
5311                               &ctx->block_dup_map);
5312                         if (pctx.errcode) {
5313                                 pctx.num = 3;
5314                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
5315                                             &pctx);
5316                                 /* Should never get here */
5317                                 ctx->flags |= E2F_FLAG_ABORT;
5318                                 return;
5319                         }
5320                 }
5321                 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
5322         } else {
5323                 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
5324         }
5325 }
5326
5327 /*
5328  * Adjust the extended attribute block's reference counts at the end
5329  * of pass 1, either by subtracting out references for EA blocks that
5330  * are still referenced in ctx->refcount, or by adding references for
5331  * EA blocks that had extra references as accounted for in
5332  * ctx->refcount_extra.
5333  */
5334 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
5335                                     char *block_buf, int adjust_sign)
5336 {
5337         struct ext2_ext_attr_header     *header;
5338         struct problem_context          pctx;
5339         ext2_filsys                     fs = ctx->fs;
5340         blk_t                           blk;
5341         __u32                           should_be;
5342         int                             count;
5343
5344         clear_problem_context(&pctx);
5345
5346         ea_refcount_intr_begin(refcount);
5347         while (1) {
5348                 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
5349                         break;
5350                 pctx.blk = blk;
5351                 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
5352                 if (pctx.errcode) {
5353                         fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
5354                         return;
5355                 }
5356                 header = (struct ext2_ext_attr_header *) block_buf;
5357                 pctx.blkcount = header->h_refcount;
5358                 should_be = header->h_refcount + adjust_sign * count;
5359                 pctx.num = should_be;
5360                 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
5361                         header->h_refcount = should_be;
5362                         pctx.errcode = ext2fs_write_ext_attr(fs, blk,
5363                                                              block_buf);
5364                         if (pctx.errcode) {
5365                                 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
5366                                 continue;
5367                         }
5368                 }
5369         }
5370 }
5371
5372 /*
5373  * Handle processing the extended attribute blocks
5374  */
5375 static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
5376                            char *block_buf)
5377 {
5378         ext2_filsys fs = ctx->fs;
5379         ext2_ino_t      ino = pctx->ino;
5380         struct ext2_inode *inode = pctx->inode;
5381         blk_t           blk;
5382         char *          end;
5383         struct ext2_ext_attr_header *header;
5384         struct ext2_ext_attr_entry *entry;
5385         int             count;
5386         region_t        region;
5387
5388         blk = inode->i_file_acl;
5389         if (blk == 0)
5390                 return 0;
5391
5392         /*
5393          * If the Extended attribute flag isn't set, then a non-zero
5394          * file acl means that the inode is corrupted.
5395          *
5396          * Or if the extended attribute block is an invalid block,
5397          * then the inode is also corrupted.
5398          */
5399         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
5400             (blk < fs->super->s_first_data_block) ||
5401             (blk >= fs->super->s_blocks_count)) {
5402                 mark_inode_bad(ctx, ino);
5403                 return 0;
5404         }
5405
5406         /* If ea bitmap hasn't been allocated, create it */
5407         if (!ctx->block_ea_map) {
5408                 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
5409                                                       _("ext attr block map"),
5410                                                       &ctx->block_ea_map);
5411                 if (pctx->errcode) {
5412                         pctx->num = 2;
5413                         fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
5414                         ctx->flags |= E2F_FLAG_ABORT;
5415                         return 0;
5416                 }
5417         }
5418
5419         /* Create the EA refcount structure if necessary */
5420         if (!ctx->refcount) {
5421                 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
5422                 if (pctx->errcode) {
5423                         pctx->num = 1;
5424                         fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
5425                         ctx->flags |= E2F_FLAG_ABORT;
5426                         return 0;
5427                 }
5428         }
5429
5430 #if 0
5431         /* Debugging text */
5432         printf("Inode %u has EA block %u\n", ino, blk);
5433 #endif
5434
5435         /* Have we seen this EA block before? */
5436         if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
5437                 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
5438                         return 1;
5439                 /* Ooops, this EA was referenced more than it stated */
5440                 if (!ctx->refcount_extra) {
5441                         pctx->errcode = ea_refcount_create(0,
5442                                            &ctx->refcount_extra);
5443                         if (pctx->errcode) {
5444                                 pctx->num = 2;
5445                                 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
5446                                 ctx->flags |= E2F_FLAG_ABORT;
5447                                 return 0;
5448                         }
5449                 }
5450                 ea_refcount_increment(ctx->refcount_extra, blk, 0);
5451                 return 1;
5452         }
5453
5454         /*
5455          * OK, we haven't seen this EA block yet.  So we need to
5456          * validate it
5457          */
5458         pctx->blk = blk;
5459         pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
5460         if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
5461                 goto clear_extattr;
5462         header = (struct ext2_ext_attr_header *) block_buf;
5463         pctx->blk = inode->i_file_acl;
5464         if (((ctx->ext_attr_ver == 1) &&
5465              (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
5466             ((ctx->ext_attr_ver == 2) &&
5467              (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
5468                 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
5469                         goto clear_extattr;
5470         }
5471
5472         if (header->h_blocks != 1) {
5473                 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
5474                         goto clear_extattr;
5475         }
5476
5477         region = region_create(0, fs->blocksize);
5478         if (!region) {
5479                 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
5480                 ctx->flags |= E2F_FLAG_ABORT;
5481                 return 0;
5482         }
5483         if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
5484                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5485                         goto clear_extattr;
5486         }
5487
5488         entry = (struct ext2_ext_attr_entry *)(header+1);
5489         end = block_buf + fs->blocksize;
5490         while ((char *)entry < end && *(__u32 *)entry) {
5491                 if (region_allocate(region, (char *)entry - (char *)header,
5492                                    EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
5493                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5494                                 goto clear_extattr;
5495                 }
5496                 if ((ctx->ext_attr_ver == 1 &&
5497                      (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
5498                     (ctx->ext_attr_ver == 2 &&
5499                      entry->e_name_index == 0)) {
5500                         if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
5501                                 goto clear_extattr;
5502                 }
5503                 if (entry->e_value_block != 0) {
5504                         if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
5505                                 goto clear_extattr;
5506                 }
5507                 if (entry->e_value_size &&
5508                     region_allocate(region, entry->e_value_offs,
5509                                     EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
5510                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5511                                 goto clear_extattr;
5512                 }
5513                 entry = EXT2_EXT_ATTR_NEXT(entry);
5514         }
5515         if (region_allocate(region, (char *)entry - (char *)header, 4)) {
5516                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5517                         goto clear_extattr;
5518         }
5519         region_free(region);
5520
5521         count = header->h_refcount - 1;
5522         if (count)
5523                 ea_refcount_store(ctx->refcount, blk, count);
5524         mark_block_used(ctx, blk);
5525         ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
5526
5527         return 1;
5528
5529 clear_extattr:
5530         inode->i_file_acl = 0;
5531         e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
5532         return 0;
5533 }
5534
5535 /* Returns 1 if bad htree, 0 if OK */
5536 static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
5537                         ext2_ino_t ino FSCK_ATTR((unused)),
5538                         struct ext2_inode *inode,
5539                         char *block_buf)
5540 {
5541         struct ext2_dx_root_info        *root;
5542         ext2_filsys                     fs = ctx->fs;
5543         errcode_t                       retval;
5544         blk_t                           blk;
5545
5546         if ((!LINUX_S_ISDIR(inode->i_mode) &&
5547              fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
5548             (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
5549              fix_problem(ctx, PR_1_HTREE_SET, pctx)))
5550                 return 1;
5551
5552         blk = inode->i_block[0];
5553         if (((blk == 0) ||
5554              (blk < fs->super->s_first_data_block) ||
5555              (blk >= fs->super->s_blocks_count)) &&
5556             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5557                 return 1;
5558
5559         retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
5560         if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5561                 return 1;
5562
5563         /* XXX should check that beginning matches a directory */
5564         root = (struct ext2_dx_root_info *) (block_buf + 24);
5565
5566         if ((root->reserved_zero || root->info_length < 8) &&
5567             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5568                 return 1;
5569
5570         pctx->num = root->hash_version;
5571         if ((root->hash_version != EXT2_HASH_LEGACY) &&
5572             (root->hash_version != EXT2_HASH_HALF_MD4) &&
5573             (root->hash_version != EXT2_HASH_TEA) &&
5574             fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
5575                 return 1;
5576
5577         if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
5578             fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
5579                 return 1;
5580
5581         pctx->num = root->indirect_levels;
5582         if ((root->indirect_levels > 1) &&
5583             fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
5584                 return 1;
5585
5586         return 0;
5587 }
5588
5589 /*
5590  * This subroutine is called on each inode to account for all of the
5591  * blocks used by that inode.
5592  */
5593 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
5594                          char *block_buf)
5595 {
5596         ext2_filsys fs = ctx->fs;
5597         struct process_block_struct_1 pb;
5598         ext2_ino_t      ino = pctx->ino;
5599         struct ext2_inode *inode = pctx->inode;
5600         int             bad_size = 0;
5601         int             dirty_inode = 0;
5602         __u64           size;
5603
5604         pb.ino = ino;
5605         pb.num_blocks = 0;
5606         pb.last_block = -1;
5607         pb.num_illegal_blocks = 0;
5608         pb.suppress = 0; pb.clear = 0;
5609         pb.fragmented = 0;
5610         pb.compressed = 0;
5611         pb.previous_block = 0;
5612         pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
5613         pb.is_reg = LINUX_S_ISREG(inode->i_mode);
5614         pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
5615         pb.inode = inode;
5616         pb.pctx = pctx;
5617         pb.ctx = ctx;
5618         pctx->ino = ino;
5619         pctx->errcode = 0;
5620
5621         if (inode->i_flags & EXT2_COMPRBLK_FL) {
5622                 if (fs->super->s_feature_incompat &
5623                     EXT2_FEATURE_INCOMPAT_COMPRESSION)
5624                         pb.compressed = 1;
5625                 else {
5626                         if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
5627                                 inode->i_flags &= ~EXT2_COMPRBLK_FL;
5628                                 dirty_inode++;
5629                         }
5630                 }
5631         }
5632
5633         if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
5634                 pb.num_blocks++;
5635
5636         if (ext2fs_inode_has_valid_blocks(inode))
5637                 pctx->errcode = ext2fs_block_iterate2(fs, ino,
5638                                        pb.is_dir ? BLOCK_FLAG_HOLE : 0,
5639                                        block_buf, process_block, &pb);
5640         end_problem_latch(ctx, PR_LATCH_BLOCK);
5641         end_problem_latch(ctx, PR_LATCH_TOOBIG);
5642         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5643                 goto out;
5644         if (pctx->errcode)
5645                 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
5646
5647         if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
5648                 ctx->fs_fragmented++;
5649
5650         if (pb.clear) {
5651                 inode->i_links_count = 0;
5652                 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
5653                 inode->i_dtime = time(0);
5654                 dirty_inode++;
5655                 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5656                 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
5657                 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5658                 /*
5659                  * The inode was probably partially accounted for
5660                  * before processing was aborted, so we need to
5661                  * restart the pass 1 scan.
5662                  */
5663                 ctx->flags |= E2F_FLAG_RESTART;
5664                 goto out;
5665         }
5666
5667         if (inode->i_flags & EXT2_INDEX_FL) {
5668                 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
5669                         inode->i_flags &= ~EXT2_INDEX_FL;
5670                         dirty_inode++;
5671                 } else {
5672 #ifdef ENABLE_HTREE
5673                         e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
5674 #endif
5675                 }
5676         }
5677         if (ctx->dirs_to_hash && pb.is_dir &&
5678             !(inode->i_flags & EXT2_INDEX_FL) &&
5679             ((inode->i_size / fs->blocksize) >= 3))
5680                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
5681
5682         if (!pb.num_blocks && pb.is_dir) {
5683                 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
5684                         inode->i_links_count = 0;
5685                         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
5686                         inode->i_dtime = time(0);
5687                         dirty_inode++;
5688                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5689                         ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
5690                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5691                         ctx->fs_directory_count--;
5692                         goto out;
5693                 }
5694         }
5695
5696         pb.num_blocks *= (fs->blocksize / 512);
5697 #if 0
5698         printf("inode %u, i_size = %lu, last_block = %lld, i_blocks=%lu, num_blocks = %lu\n",
5699                ino, inode->i_size, pb.last_block, inode->i_blocks,
5700                pb.num_blocks);
5701 #endif
5702         if (pb.is_dir) {
5703                 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
5704                 if (nblock > (pb.last_block + 1))
5705                         bad_size = 1;
5706                 else if (nblock < (pb.last_block + 1)) {
5707                         if (((pb.last_block + 1) - nblock) >
5708                             fs->super->s_prealloc_dir_blocks)
5709                                 bad_size = 2;
5710                 }
5711         } else {
5712                 size = EXT2_I_SIZE(inode);
5713                 if ((pb.last_block >= 0) &&
5714                     (size < (__u64) pb.last_block * fs->blocksize))
5715                         bad_size = 3;
5716                 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
5717                         bad_size = 4;
5718         }
5719         /* i_size for symlinks is checked elsewhere */
5720         if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
5721                 pctx->num = (pb.last_block+1) * fs->blocksize;
5722                 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
5723                         inode->i_size = pctx->num;
5724                         if (!LINUX_S_ISDIR(inode->i_mode))
5725                                 inode->i_size_high = pctx->num >> 32;
5726                         dirty_inode++;
5727                 }
5728                 pctx->num = 0;
5729         }
5730         if (LINUX_S_ISREG(inode->i_mode) &&
5731             (inode->i_size_high || inode->i_size & 0x80000000UL))
5732                 ctx->large_files++;
5733         if (pb.num_blocks != inode->i_blocks) {
5734                 pctx->num = pb.num_blocks;
5735                 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
5736                         inode->i_blocks = pb.num_blocks;
5737                         dirty_inode++;
5738                 }
5739                 pctx->num = 0;
5740         }
5741 out:
5742         if (dirty_inode)
5743                 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
5744 }
5745
5746 #if 0
5747 /*
5748  * Helper function called by process block when an illegal block is
5749  * found.  It returns a description about why the block is illegal
5750  */
5751 static char *describe_illegal_block(ext2_filsys fs, blk_t block)
5752 {
5753         blk_t   super;
5754         int     i;
5755         static char     problem[80];
5756
5757         super = fs->super->s_first_data_block;
5758         strcpy(problem, "PROGRAMMING ERROR: Unknown reason for illegal block");
5759         if (block < super) {
5760                 sprintf(problem, "< FIRSTBLOCK (%u)", super);
5761                 return(problem);
5762         } else if (block >= fs->super->s_blocks_count) {
5763                 sprintf(problem, "> BLOCKS (%u)", fs->super->s_blocks_count);
5764                 return(problem);
5765         }
5766         for (i = 0; i < fs->group_desc_count; i++) {
5767                 if (block == super) {
5768                         sprintf(problem, "is the superblock in group %d", i);
5769                         break;
5770                 }
5771                 if (block > super &&
5772                     block <= (super + fs->desc_blocks)) {
5773                         sprintf(problem, "is in the group descriptors "
5774                                 "of group %d", i);
5775                         break;
5776                 }
5777                 if (block == fs->group_desc[i].bg_block_bitmap) {
5778                         sprintf(problem, "is the block bitmap of group %d", i);
5779                         break;
5780                 }
5781                 if (block == fs->group_desc[i].bg_inode_bitmap) {
5782                         sprintf(problem, "is the inode bitmap of group %d", i);
5783                         break;
5784                 }
5785                 if (block >= fs->group_desc[i].bg_inode_table &&
5786                     (block < fs->group_desc[i].bg_inode_table
5787                      + fs->inode_blocks_per_group)) {
5788                         sprintf(problem, "is in the inode table of group %d",
5789                                 i);
5790                         break;
5791                 }
5792                 super += fs->super->s_blocks_per_group;
5793         }
5794         return(problem);
5795 }
5796 #endif
5797
5798 /*
5799  * This is a helper function for check_blocks().
5800  */
5801 static int process_block(ext2_filsys fs,
5802                   blk_t *block_nr,
5803                   e2_blkcnt_t blockcnt,
5804                   blk_t ref_block FSCK_ATTR((unused)),
5805                   int ref_offset FSCK_ATTR((unused)),
5806                   void *priv_data)
5807 {
5808         struct process_block_struct_1 *p;
5809         struct problem_context *pctx;
5810         blk_t   blk = *block_nr;
5811         int     ret_code = 0;
5812         int     problem = 0;
5813         e2fsck_t        ctx;
5814
5815         p = (struct process_block_struct_1 *) priv_data;
5816         pctx = p->pctx;
5817         ctx = p->ctx;
5818
5819         if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
5820                 /* todo: Check that the comprblk_fl is high, that the
5821                    blkaddr pattern looks right (all non-holes up to
5822                    first EXT2FS_COMPRESSED_BLKADDR, then all
5823                    EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
5824                    that the feature_incompat bit is high, and that the
5825                    inode is a regular file.  If we're doing a "full
5826                    check" (a concept introduced to e2fsck by e2compr,
5827                    meaning that we look at data blocks as well as
5828                    metadata) then call some library routine that
5829                    checks the compressed data.  I'll have to think
5830                    about this, because one particularly important
5831                    problem to be able to fix is to recalculate the
5832                    cluster size if necessary.  I think that perhaps
5833                    we'd better do most/all e2compr-specific checks
5834                    separately, after the non-e2compr checks.  If not
5835                    doing a full check, it may be useful to test that
5836                    the personality is linux; e.g. if it isn't then
5837                    perhaps this really is just an illegal block. */
5838                 return 0;
5839         }
5840
5841         if (blk == 0) {
5842                 if (p->is_dir == 0) {
5843                         /*
5844                          * Should never happen, since only directories
5845                          * get called with BLOCK_FLAG_HOLE
5846                          */
5847 #if DEBUG_E2FSCK
5848                         printf("process_block() called with blk == 0, "
5849                                "blockcnt=%d, inode %lu???\n",
5850                                blockcnt, p->ino);
5851 #endif
5852                         return 0;
5853                 }
5854                 if (blockcnt < 0)
5855                         return 0;
5856                 if (blockcnt * fs->blocksize < p->inode->i_size) {
5857 #if 0
5858                         printf("Missing block (#%d) in directory inode %lu!\n",
5859                                blockcnt, p->ino);
5860 #endif
5861                         goto mark_dir;
5862                 }
5863                 return 0;
5864         }
5865
5866 #if 0
5867         printf("Process_block, inode %lu, block %u, #%d\n", p->ino, blk,
5868                blockcnt);
5869 #endif
5870
5871         /*
5872          * Simplistic fragmentation check.  We merely require that the
5873          * file be contiguous.  (Which can never be true for really
5874          * big files that are greater than a block group.)
5875          */
5876         if (!HOLE_BLKADDR(p->previous_block)) {
5877                 if (p->previous_block+1 != blk)
5878                         p->fragmented = 1;
5879         }
5880         p->previous_block = blk;
5881
5882         if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
5883                 problem = PR_1_TOOBIG_DIR;
5884         if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
5885                 problem = PR_1_TOOBIG_REG;
5886         if (!p->is_dir && !p->is_reg && blockcnt > 0)
5887                 problem = PR_1_TOOBIG_SYMLINK;
5888
5889         if (blk < fs->super->s_first_data_block ||
5890             blk >= fs->super->s_blocks_count)
5891                 problem = PR_1_ILLEGAL_BLOCK_NUM;
5892
5893         if (problem) {
5894                 p->num_illegal_blocks++;
5895                 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
5896                         if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
5897                                 p->clear = 1;
5898                                 return BLOCK_ABORT;
5899                         }
5900                         if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
5901                                 p->suppress = 1;
5902                                 set_latch_flags(PR_LATCH_BLOCK,
5903                                                 PRL_SUPPRESS, 0);
5904                         }
5905                 }
5906                 pctx->blk = blk;
5907                 pctx->blkcount = blockcnt;
5908                 if (fix_problem(ctx, problem, pctx)) {
5909                         blk = *block_nr = 0;
5910                         ret_code = BLOCK_CHANGED;
5911                         goto mark_dir;
5912                 } else
5913                         return 0;
5914         }
5915
5916         if (p->ino == EXT2_RESIZE_INO) {
5917                 /*
5918                  * The resize inode has already be sanity checked
5919                  * during pass #0 (the superblock checks).  All we
5920                  * have to do is mark the double indirect block as
5921                  * being in use; all of the other blocks are handled
5922                  * by mark_table_blocks()).
5923                  */
5924                 if (blockcnt == BLOCK_COUNT_DIND)
5925                         mark_block_used(ctx, blk);
5926         } else
5927                 mark_block_used(ctx, blk);
5928         p->num_blocks++;
5929         if (blockcnt >= 0)
5930                 p->last_block = blockcnt;
5931 mark_dir:
5932         if (p->is_dir && (blockcnt >= 0)) {
5933                 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
5934                                                     blk, blockcnt);
5935                 if (pctx->errcode) {
5936                         pctx->blk = blk;
5937                         pctx->num = blockcnt;
5938                         fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
5939                         /* Should never get here */
5940                         ctx->flags |= E2F_FLAG_ABORT;
5941                         return BLOCK_ABORT;
5942                 }
5943         }
5944         return ret_code;
5945 }
5946
5947 static int process_bad_block(ext2_filsys fs,
5948                       blk_t *block_nr,
5949                       e2_blkcnt_t blockcnt,
5950                       blk_t ref_block FSCK_ATTR((unused)),
5951                       int ref_offset FSCK_ATTR((unused)),
5952                       void *priv_data)
5953 {
5954         struct process_block_struct_1 *p;
5955         blk_t           blk = *block_nr;
5956         blk_t           first_block;
5957         dgrp_t          i;
5958         struct problem_context *pctx;
5959         e2fsck_t        ctx;
5960
5961         /*
5962          * Note: This function processes blocks for the bad blocks
5963          * inode, which is never compressed.  So we don't use HOLE_BLKADDR().
5964          */
5965
5966         if (!blk)
5967                 return 0;
5968
5969         p = (struct process_block_struct_1 *) priv_data;
5970         ctx = p->ctx;
5971         pctx = p->pctx;
5972
5973         pctx->ino = EXT2_BAD_INO;
5974         pctx->blk = blk;
5975         pctx->blkcount = blockcnt;
5976
5977         if ((blk < fs->super->s_first_data_block) ||
5978             (blk >= fs->super->s_blocks_count)) {
5979                 if (fix_problem(ctx, PR_1_BB_ILLEGAL_BLOCK_NUM, pctx)) {
5980                         *block_nr = 0;
5981                         return BLOCK_CHANGED;
5982                 } else
5983                         return 0;
5984         }
5985
5986         if (blockcnt < 0) {
5987                 if (ext2fs_test_block_bitmap(p->fs_meta_blocks, blk)) {
5988                         p->bbcheck = 1;
5989                         if (fix_problem(ctx, PR_1_BB_FS_BLOCK, pctx)) {
5990                                 *block_nr = 0;
5991                                 return BLOCK_CHANGED;
5992                         }
5993                 } else if (ext2fs_test_block_bitmap(ctx->block_found_map,
5994                                                     blk)) {
5995                         p->bbcheck = 1;
5996                         if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK,
5997                                         pctx)) {
5998                                 *block_nr = 0;
5999                                 return BLOCK_CHANGED;
6000                         }
6001                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6002                                 return BLOCK_ABORT;
6003                 } else
6004                         mark_block_used(ctx, blk);
6005                 return 0;
6006         }
6007 #if 0
6008         printf ("DEBUG: Marking %u as bad.\n", blk);
6009 #endif
6010         ctx->fs_badblocks_count++;
6011         /*
6012          * If the block is not used, then mark it as used and return.
6013          * If it is already marked as found, this must mean that
6014          * there's an overlap between the filesystem table blocks
6015          * (bitmaps and inode table) and the bad block list.
6016          */
6017         if (!ext2fs_test_block_bitmap(ctx->block_found_map, blk)) {
6018                 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6019                 return 0;
6020         }
6021         /*
6022          * Try to find the where the filesystem block was used...
6023          */
6024         first_block = fs->super->s_first_data_block;
6025
6026         for (i = 0; i < fs->group_desc_count; i++ ) {
6027                 pctx->group = i;
6028                 pctx->blk = blk;
6029                 if (!ext2fs_bg_has_super(fs, i))
6030                         goto skip_super;
6031                 if (blk == first_block) {
6032                         if (i == 0) {
6033                                 if (fix_problem(ctx,
6034                                                 PR_1_BAD_PRIMARY_SUPERBLOCK,
6035                                                 pctx)) {
6036                                         *block_nr = 0;
6037                                         return BLOCK_CHANGED;
6038                                 }
6039                                 return 0;
6040                         }
6041                         fix_problem(ctx, PR_1_BAD_SUPERBLOCK, pctx);
6042                         return 0;
6043                 }
6044                 if ((blk > first_block) &&
6045                     (blk <= first_block + fs->desc_blocks)) {
6046                         if (i == 0) {
6047                                 pctx->blk = *block_nr;
6048                                 if (fix_problem(ctx,
6049                         PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR, pctx)) {
6050                                         *block_nr = 0;
6051                                         return BLOCK_CHANGED;
6052                                 }
6053                                 return 0;
6054                         }
6055                         fix_problem(ctx, PR_1_BAD_GROUP_DESCRIPTORS, pctx);
6056                         return 0;
6057                 }
6058         skip_super:
6059                 if (blk == fs->group_desc[i].bg_block_bitmap) {
6060                         if (fix_problem(ctx, PR_1_BB_BAD_BLOCK, pctx)) {
6061                                 ctx->invalid_block_bitmap_flag[i]++;
6062                                 ctx->invalid_bitmaps++;
6063                         }
6064                         return 0;
6065                 }
6066                 if (blk == fs->group_desc[i].bg_inode_bitmap) {
6067                         if (fix_problem(ctx, PR_1_IB_BAD_BLOCK, pctx)) {
6068                                 ctx->invalid_inode_bitmap_flag[i]++;
6069                                 ctx->invalid_bitmaps++;
6070                         }
6071                         return 0;
6072                 }
6073                 if ((blk >= fs->group_desc[i].bg_inode_table) &&
6074                     (blk < (fs->group_desc[i].bg_inode_table +
6075                             fs->inode_blocks_per_group))) {
6076                         /*
6077                          * If there are bad blocks in the inode table,
6078                          * the inode scan code will try to do
6079                          * something reasonable automatically.
6080                          */
6081                         return 0;
6082                 }
6083                 first_block += fs->super->s_blocks_per_group;
6084         }
6085         /*
6086          * If we've gotten to this point, then the only
6087          * possibility is that the bad block inode meta data
6088          * is using a bad block.
6089          */
6090         if ((blk == p->inode->i_block[EXT2_IND_BLOCK]) ||
6091             (blk == p->inode->i_block[EXT2_DIND_BLOCK]) ||
6092             (blk == p->inode->i_block[EXT2_TIND_BLOCK])) {
6093                 p->bbcheck = 1;
6094                 if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK, pctx)) {
6095                         *block_nr = 0;
6096                         return BLOCK_CHANGED;
6097                 }
6098                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6099                         return BLOCK_ABORT;
6100                 return 0;
6101         }
6102
6103         pctx->group = -1;
6104
6105         /* Warn user that the block wasn't claimed */
6106         fix_problem(ctx, PR_1_PROGERR_CLAIMED_BLOCK, pctx);
6107
6108         return 0;
6109 }
6110
6111 static void new_table_block(e2fsck_t ctx, blk_t first_block, int group,
6112                             const char *name, int num, blk_t *new_block)
6113 {
6114         ext2_filsys fs = ctx->fs;
6115         blk_t           old_block = *new_block;
6116         int             i;
6117         char            *buf;
6118         struct problem_context  pctx;
6119
6120         clear_problem_context(&pctx);
6121
6122         pctx.group = group;
6123         pctx.blk = old_block;
6124         pctx.str = name;
6125
6126         pctx.errcode = ext2fs_get_free_blocks(fs, first_block,
6127                         first_block + fs->super->s_blocks_per_group,
6128                                         num, ctx->block_found_map, new_block);
6129         if (pctx.errcode) {
6130                 pctx.num = num;
6131                 fix_problem(ctx, PR_1_RELOC_BLOCK_ALLOCATE, &pctx);
6132                 ext2fs_unmark_valid(fs);
6133                 return;
6134         }
6135         pctx.errcode = ext2fs_get_mem(fs->blocksize, &buf);
6136         if (pctx.errcode) {
6137                 fix_problem(ctx, PR_1_RELOC_MEMORY_ALLOCATE, &pctx);
6138                 ext2fs_unmark_valid(fs);
6139                 return;
6140         }
6141         ext2fs_mark_super_dirty(fs);
6142         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
6143         pctx.blk2 = *new_block;
6144         fix_problem(ctx, (old_block ? PR_1_RELOC_FROM_TO :
6145                           PR_1_RELOC_TO), &pctx);
6146         pctx.blk2 = 0;
6147         for (i = 0; i < num; i++) {
6148                 pctx.blk = i;
6149                 ext2fs_mark_block_bitmap(ctx->block_found_map, (*new_block)+i);
6150                 if (old_block) {
6151                         pctx.errcode = io_channel_read_blk(fs->io,
6152                                    old_block + i, 1, buf);
6153                         if (pctx.errcode)
6154                                 fix_problem(ctx, PR_1_RELOC_READ_ERR, &pctx);
6155                 } else
6156                         memset(buf, 0, fs->blocksize);
6157
6158                 pctx.blk = (*new_block) + i;
6159                 pctx.errcode = io_channel_write_blk(fs->io, pctx.blk,
6160                                               1, buf);
6161                 if (pctx.errcode)
6162                         fix_problem(ctx, PR_1_RELOC_WRITE_ERR, &pctx);
6163         }
6164         ext2fs_free_mem(&buf);
6165 }
6166
6167 /*
6168  * This routine gets called at the end of pass 1 if bad blocks are
6169  * detected in the superblock, group descriptors, inode_bitmaps, or
6170  * block bitmaps.  At this point, all of the blocks have been mapped
6171  * out, so we can try to allocate new block(s) to replace the bad
6172  * blocks.
6173  */
6174 static void handle_fs_bad_blocks(e2fsck_t ctx)
6175 {
6176         ext2_filsys fs = ctx->fs;
6177         dgrp_t          i;
6178         int             first_block = fs->super->s_first_data_block;
6179
6180         for (i = 0; i < fs->group_desc_count; i++) {
6181                 if (ctx->invalid_block_bitmap_flag[i]) {
6182                         new_table_block(ctx, first_block, i, _("block bitmap"),
6183                                         1, &fs->group_desc[i].bg_block_bitmap);
6184                 }
6185                 if (ctx->invalid_inode_bitmap_flag[i]) {
6186                         new_table_block(ctx, first_block, i, _("inode bitmap"),
6187                                         1, &fs->group_desc[i].bg_inode_bitmap);
6188                 }
6189                 if (ctx->invalid_inode_table_flag[i]) {
6190                         new_table_block(ctx, first_block, i, _("inode table"),
6191                                         fs->inode_blocks_per_group,
6192                                         &fs->group_desc[i].bg_inode_table);
6193                         ctx->flags |= E2F_FLAG_RESTART;
6194                 }
6195                 first_block += fs->super->s_blocks_per_group;
6196         }
6197         ctx->invalid_bitmaps = 0;
6198 }
6199
6200 /*
6201  * This routine marks all blocks which are used by the superblock,
6202  * group descriptors, inode bitmaps, and block bitmaps.
6203  */
6204 static void mark_table_blocks(e2fsck_t ctx)
6205 {
6206         ext2_filsys fs = ctx->fs;
6207         blk_t   block, b;
6208         dgrp_t  i;
6209         int     j;
6210         struct problem_context pctx;
6211
6212         clear_problem_context(&pctx);
6213
6214         block = fs->super->s_first_data_block;
6215         for (i = 0; i < fs->group_desc_count; i++) {
6216                 pctx.group = i;
6217
6218                 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
6219
6220                 /*
6221                  * Mark the blocks used for the inode table
6222                  */
6223                 if (fs->group_desc[i].bg_inode_table) {
6224                         for (j = 0, b = fs->group_desc[i].bg_inode_table;
6225                              j < fs->inode_blocks_per_group;
6226                              j++, b++) {
6227                                 if (ext2fs_test_block_bitmap(ctx->block_found_map,
6228                                                              b)) {
6229                                         pctx.blk = b;
6230                                         if (fix_problem(ctx,
6231                                                 PR_1_ITABLE_CONFLICT, &pctx)) {
6232                                                 ctx->invalid_inode_table_flag[i]++;
6233                                                 ctx->invalid_bitmaps++;
6234                                         }
6235                                 } else {
6236                                     ext2fs_mark_block_bitmap(ctx->block_found_map,
6237                                                              b);
6238                                 }
6239                         }
6240                 }
6241
6242                 /*
6243                  * Mark block used for the block bitmap
6244                  */
6245                 if (fs->group_desc[i].bg_block_bitmap) {
6246                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
6247                                      fs->group_desc[i].bg_block_bitmap)) {
6248                                 pctx.blk = fs->group_desc[i].bg_block_bitmap;
6249                                 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
6250                                         ctx->invalid_block_bitmap_flag[i]++;
6251                                         ctx->invalid_bitmaps++;
6252                                 }
6253                         } else {
6254                             ext2fs_mark_block_bitmap(ctx->block_found_map,
6255                                      fs->group_desc[i].bg_block_bitmap);
6256                     }
6257
6258                 }
6259                 /*
6260                  * Mark block used for the inode bitmap
6261                  */
6262                 if (fs->group_desc[i].bg_inode_bitmap) {
6263                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
6264                                      fs->group_desc[i].bg_inode_bitmap)) {
6265                                 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
6266                                 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
6267                                         ctx->invalid_inode_bitmap_flag[i]++;
6268                                         ctx->invalid_bitmaps++;
6269                                 }
6270                         } else {
6271                             ext2fs_mark_block_bitmap(ctx->block_found_map,
6272                                      fs->group_desc[i].bg_inode_bitmap);
6273                         }
6274                 }
6275                 block += fs->super->s_blocks_per_group;
6276         }
6277 }
6278
6279 /*
6280  * Thes subroutines short circuits ext2fs_get_blocks and
6281  * ext2fs_check_directory; we use them since we already have the inode
6282  * structure, so there's no point in letting the ext2fs library read
6283  * the inode again.
6284  */
6285 static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
6286                                   blk_t *blocks)
6287 {
6288         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6289         int     i;
6290
6291         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
6292                 return EXT2_ET_CALLBACK_NOTHANDLED;
6293
6294         for (i=0; i < EXT2_N_BLOCKS; i++)
6295                 blocks[i] = ctx->stashed_inode->i_block[i];
6296         return 0;
6297 }
6298
6299 static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
6300                                   struct ext2_inode *inode)
6301 {
6302         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6303
6304         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
6305                 return EXT2_ET_CALLBACK_NOTHANDLED;
6306         *inode = *ctx->stashed_inode;
6307         return 0;
6308 }
6309
6310 static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
6311                             struct ext2_inode *inode)
6312 {
6313         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6314
6315         if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
6316                 *ctx->stashed_inode = *inode;
6317         return EXT2_ET_CALLBACK_NOTHANDLED;
6318 }
6319
6320 static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
6321 {
6322         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6323
6324         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
6325                 return EXT2_ET_CALLBACK_NOTHANDLED;
6326
6327         if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
6328                 return EXT2_ET_NO_DIRECTORY;
6329         return 0;
6330 }
6331
6332 void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
6333 {
6334         ext2_filsys fs = ctx->fs;
6335
6336         if (bool) {
6337                 fs->get_blocks = pass1_get_blocks;
6338                 fs->check_directory = pass1_check_directory;
6339                 fs->read_inode = pass1_read_inode;
6340                 fs->write_inode = pass1_write_inode;
6341                 ctx->stashed_ino = 0;
6342         } else {
6343                 fs->get_blocks = 0;
6344                 fs->check_directory = 0;
6345                 fs->read_inode = 0;
6346                 fs->write_inode = 0;
6347         }
6348 }
6349
6350 /*
6351  * pass1b.c --- Pass #1b of e2fsck
6352  *
6353  * This file contains pass1B, pass1C, and pass1D of e2fsck.  They are
6354  * only invoked if pass 1 discovered blocks which are in use by more
6355  * than one inode.
6356  *
6357  * Pass1B scans the data blocks of all the inodes again, generating a
6358  * complete list of duplicate blocks and which inodes have claimed
6359  * them.
6360  *
6361  * Pass1C does a tree-traversal of the filesystem, to determine the
6362  * parent directories of these inodes.  This step is necessary so that
6363  * e2fsck can print out the pathnames of affected inodes.
6364  *
6365  * Pass1D is a reconciliation pass.  For each inode with duplicate
6366  * blocks, the user is prompted if s/he would like to clone the file
6367  * (so that the file gets a fresh copy of the duplicated blocks) or
6368  * simply to delete the file.
6369  *
6370  */
6371
6372
6373 /* Needed for architectures where sizeof(int) != sizeof(void *) */
6374 #define INT_TO_VOIDPTR(val)  ((void *)(intptr_t)(val))
6375 #define VOIDPTR_TO_INT(ptr)  ((int)(intptr_t)(ptr))
6376
6377 /* Define an extension to the ext2 library's block count information */
6378 #define BLOCK_COUNT_EXTATTR     (-5)
6379
6380 struct block_el {
6381         blk_t   block;
6382         struct block_el *next;
6383 };
6384
6385 struct inode_el {
6386         ext2_ino_t      inode;
6387         struct inode_el *next;
6388 };
6389
6390 struct dup_block {
6391         int             num_bad;
6392         struct inode_el *inode_list;
6393 };
6394
6395 /*
6396  * This structure stores information about a particular inode which
6397  * is sharing blocks with other inodes.  This information is collected
6398  * to display to the user, so that the user knows what files he or she
6399  * is dealing with, when trying to decide how to resolve the conflict
6400  * of multiply-claimed blocks.
6401  */
6402 struct dup_inode {
6403         ext2_ino_t              dir;
6404         int                     num_dupblocks;
6405         struct ext2_inode       inode;
6406         struct block_el         *block_list;
6407 };
6408
6409 static int process_pass1b_block(ext2_filsys fs, blk_t   *blocknr,
6410                                 e2_blkcnt_t blockcnt, blk_t ref_blk,
6411                                 int ref_offset, void *priv_data);
6412 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
6413                         struct dup_inode *dp, char *block_buf);
6414 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
6415                       struct dup_inode *dp, char* block_buf);
6416 static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
6417
6418 static void pass1b(e2fsck_t ctx, char *block_buf);
6419 static void pass1c(e2fsck_t ctx, char *block_buf);
6420 static void pass1d(e2fsck_t ctx, char *block_buf);
6421
6422 static int dup_inode_count = 0;
6423
6424 static dict_t blk_dict, ino_dict;
6425
6426 static ext2fs_inode_bitmap inode_dup_map;
6427
6428 static int dict_int_cmp(const void *a, const void *b)
6429 {
6430         intptr_t        ia, ib;
6431
6432         ia = (intptr_t)a;
6433         ib = (intptr_t)b;
6434
6435         return (ia-ib);
6436 }
6437
6438 /*
6439  * Add a duplicate block record
6440  */
6441 static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
6442                      struct ext2_inode *inode)
6443 {
6444         dnode_t *n;
6445         struct dup_block        *db;
6446         struct dup_inode        *di;
6447         struct block_el         *blk_el;
6448         struct inode_el         *ino_el;
6449
6450         n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
6451         if (n)
6452                 db = (struct dup_block *) dnode_get(n);
6453         else {
6454                 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
6455                          sizeof(struct dup_block), "duplicate block header");
6456                 db->num_bad = 0;
6457                 db->inode_list = 0;
6458                 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
6459         }
6460         ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
6461                          sizeof(struct inode_el), "inode element");
6462         ino_el->inode = ino;
6463         ino_el->next = db->inode_list;
6464         db->inode_list = ino_el;
6465         db->num_bad++;
6466
6467         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
6468         if (n)
6469                 di = (struct dup_inode *) dnode_get(n);
6470         else {
6471                 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
6472                          sizeof(struct dup_inode), "duplicate inode header");
6473                 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0 ;
6474                 di->num_dupblocks = 0;
6475                 di->block_list = 0;
6476                 di->inode = *inode;
6477                 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
6478         }
6479         blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
6480                          sizeof(struct block_el), "block element");
6481         blk_el->block = blk;
6482         blk_el->next = di->block_list;
6483         di->block_list = blk_el;
6484         di->num_dupblocks++;
6485 }
6486
6487 /*
6488  * Free a duplicate inode record
6489  */
6490 static void inode_dnode_free(dnode_t *node)
6491 {
6492         struct dup_inode        *di;
6493         struct block_el         *p, *next;
6494
6495         di = (struct dup_inode *) dnode_get(node);
6496         for (p = di->block_list; p; p = next) {
6497                 next = p->next;
6498                 free(p);
6499         }
6500         free(node);
6501 }
6502
6503 /*
6504  * Free a duplicate block record
6505  */
6506 static void block_dnode_free(dnode_t *node)
6507 {
6508         struct dup_block        *db;
6509         struct inode_el         *p, *next;
6510
6511         db = (struct dup_block *) dnode_get(node);
6512         for (p = db->inode_list; p; p = next) {
6513                 next = p->next;
6514                 free(p);
6515         }
6516         free(node);
6517 }
6518
6519
6520 /*
6521  * Main procedure for handling duplicate blocks
6522  */
6523 void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
6524 {
6525         ext2_filsys             fs = ctx->fs;
6526         struct problem_context  pctx;
6527
6528         clear_problem_context(&pctx);
6529
6530         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
6531                       _("multiply claimed inode map"), &inode_dup_map);
6532         if (pctx.errcode) {
6533                 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
6534                 ctx->flags |= E2F_FLAG_ABORT;
6535                 return;
6536         }
6537
6538         dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
6539         dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
6540         dict_set_allocator(&ino_dict, inode_dnode_free);
6541         dict_set_allocator(&blk_dict, block_dnode_free);
6542
6543         pass1b(ctx, block_buf);
6544         pass1c(ctx, block_buf);
6545         pass1d(ctx, block_buf);
6546
6547         /*
6548          * Time to free all of the accumulated data structures that we
6549          * don't need anymore.
6550          */
6551         dict_free_nodes(&ino_dict);
6552         dict_free_nodes(&blk_dict);
6553 }
6554
6555 /*
6556  * Scan the inodes looking for inodes that contain duplicate blocks.
6557  */
6558 struct process_block_struct_1b {
6559         e2fsck_t        ctx;
6560         ext2_ino_t      ino;
6561         int             dup_blocks;
6562         struct ext2_inode *inode;
6563         struct problem_context *pctx;
6564 };
6565
6566 static void pass1b(e2fsck_t ctx, char *block_buf)
6567 {
6568         ext2_filsys fs = ctx->fs;
6569         ext2_ino_t ino;
6570         struct ext2_inode inode;
6571         ext2_inode_scan scan;
6572         struct process_block_struct_1b pb;
6573         struct problem_context pctx;
6574
6575         clear_problem_context(&pctx);
6576
6577         if (!(ctx->options & E2F_OPT_PREEN))
6578                 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
6579         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
6580                                               &scan);
6581         if (pctx.errcode) {
6582                 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
6583                 ctx->flags |= E2F_FLAG_ABORT;
6584                 return;
6585         }
6586         ctx->stashed_inode = &inode;
6587         pb.ctx = ctx;
6588         pb.pctx = &pctx;
6589         pctx.str = "pass1b";
6590         while (1) {
6591                 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
6592                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
6593                         continue;
6594                 if (pctx.errcode) {
6595                         fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
6596                         ctx->flags |= E2F_FLAG_ABORT;
6597                         return;
6598                 }
6599                 if (!ino)
6600                         break;
6601                 pctx.ino = ctx->stashed_ino = ino;
6602                 if ((ino != EXT2_BAD_INO) &&
6603                     !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
6604                         continue;
6605
6606                 pb.ino = ino;
6607                 pb.dup_blocks = 0;
6608                 pb.inode = &inode;
6609
6610                 if (ext2fs_inode_has_valid_blocks(&inode) ||
6611                     (ino == EXT2_BAD_INO))
6612                         pctx.errcode = ext2fs_block_iterate2(fs, ino,
6613                                      0, block_buf, process_pass1b_block, &pb);
6614                 if (inode.i_file_acl)
6615                         process_pass1b_block(fs, &inode.i_file_acl,
6616                                              BLOCK_COUNT_EXTATTR, 0, 0, &pb);
6617                 if (pb.dup_blocks) {
6618                         end_problem_latch(ctx, PR_LATCH_DBLOCK);
6619                         if (ino >= EXT2_FIRST_INODE(fs->super) ||
6620                             ino == EXT2_ROOT_INO)
6621                                 dup_inode_count++;
6622                 }
6623                 if (pctx.errcode)
6624                         fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
6625         }
6626         ext2fs_close_inode_scan(scan);
6627         e2fsck_use_inode_shortcuts(ctx, 0);
6628 }
6629
6630 static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
6631                                 blk_t   *block_nr,
6632                                 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6633                                 blk_t ref_blk FSCK_ATTR((unused)),
6634                                 int ref_offset FSCK_ATTR((unused)),
6635                                 void *priv_data)
6636 {
6637         struct process_block_struct_1b *p;
6638         e2fsck_t ctx;
6639
6640         if (HOLE_BLKADDR(*block_nr))
6641                 return 0;
6642         p = (struct process_block_struct_1b *) priv_data;
6643         ctx = p->ctx;
6644
6645         if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
6646                 return 0;
6647
6648         /* OK, this is a duplicate block */
6649         if (p->ino != EXT2_BAD_INO) {
6650                 p->pctx->blk = *block_nr;
6651                 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
6652         }
6653         p->dup_blocks++;
6654         ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
6655
6656         add_dupe(ctx, p->ino, *block_nr, p->inode);
6657
6658         return 0;
6659 }
6660
6661 /*
6662  * Pass 1c: Scan directories for inodes with duplicate blocks.  This
6663  * is used so that we can print pathnames when prompting the user for
6664  * what to do.
6665  */
6666 struct search_dir_struct {
6667         int             count;
6668         ext2_ino_t      first_inode;
6669         ext2_ino_t      max_inode;
6670 };
6671
6672 static int search_dirent_proc(ext2_ino_t dir, int entry,
6673                               struct ext2_dir_entry *dirent,
6674                               int offset FSCK_ATTR((unused)),
6675                               int blocksize FSCK_ATTR((unused)),
6676                               char *buf FSCK_ATTR((unused)),
6677                               void *priv_data)
6678 {
6679         struct search_dir_struct *sd;
6680         struct dup_inode        *p;
6681         dnode_t                 *n;
6682
6683         sd = (struct search_dir_struct *) priv_data;
6684
6685         if (dirent->inode > sd->max_inode)
6686                 /* Should abort this inode, but not everything */
6687                 return 0;
6688
6689         if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
6690             !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
6691                 return 0;
6692
6693         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
6694         if (!n)
6695                 return 0;
6696         p = (struct dup_inode *) dnode_get(n);
6697         p->dir = dir;
6698         sd->count--;
6699
6700         return(sd->count ? 0 : DIRENT_ABORT);
6701 }
6702
6703
6704 static void pass1c(e2fsck_t ctx, char *block_buf)
6705 {
6706         ext2_filsys fs = ctx->fs;
6707         struct search_dir_struct sd;
6708         struct problem_context pctx;
6709
6710         clear_problem_context(&pctx);
6711
6712         if (!(ctx->options & E2F_OPT_PREEN))
6713                 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
6714
6715         /*
6716          * Search through all directories to translate inodes to names
6717          * (by searching for the containing directory for that inode.)
6718          */
6719         sd.count = dup_inode_count;
6720         sd.first_inode = EXT2_FIRST_INODE(fs->super);
6721         sd.max_inode = fs->super->s_inodes_count;
6722         ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
6723                                   search_dirent_proc, &sd);
6724 }
6725
6726 static void pass1d(e2fsck_t ctx, char *block_buf)
6727 {
6728         ext2_filsys fs = ctx->fs;
6729         struct dup_inode        *p, *t;
6730         struct dup_block        *q;
6731         ext2_ino_t              *shared, ino;
6732         int     shared_len;
6733         int     i;
6734         int     file_ok;
6735         int     meta_data = 0;
6736         struct problem_context pctx;
6737         dnode_t *n, *m;
6738         struct block_el *s;
6739         struct inode_el *r;
6740
6741         clear_problem_context(&pctx);
6742
6743         if (!(ctx->options & E2F_OPT_PREEN))
6744                 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
6745         e2fsck_read_bitmaps(ctx);
6746
6747         pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
6748         fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
6749         shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
6750                                 sizeof(ext2_ino_t) * dict_count(&ino_dict),
6751                                 "Shared inode list");
6752         for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
6753                 p = (struct dup_inode *) dnode_get(n);
6754                 shared_len = 0;
6755                 file_ok = 1;
6756                 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
6757                 if (ino == EXT2_BAD_INO)
6758                         continue;
6759
6760                 /*
6761                  * Find all of the inodes which share blocks with this
6762                  * one.  First we find all of the duplicate blocks
6763                  * belonging to this inode, and then search each block
6764                  * get the list of inodes, and merge them together.
6765                  */
6766                 for (s = p->block_list; s; s = s->next) {
6767                         m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
6768                         if (!m)
6769                                 continue; /* Should never happen... */
6770                         q = (struct dup_block *) dnode_get(m);
6771                         if (q->num_bad > 1)
6772                                 file_ok = 0;
6773                         if (check_if_fs_block(ctx, s->block)) {
6774                                 file_ok = 0;
6775                                 meta_data = 1;
6776                         }
6777
6778                         /*
6779                          * Add all inodes used by this block to the
6780                          * shared[] --- which is a unique list, so
6781                          * if an inode is already in shared[], don't
6782                          * add it again.
6783                          */
6784                         for (r = q->inode_list; r; r = r->next) {
6785                                 if (r->inode == ino)
6786                                         continue;
6787                                 for (i = 0; i < shared_len; i++)
6788                                         if (shared[i] == r->inode)
6789                                                 break;
6790                                 if (i == shared_len) {
6791                                         shared[shared_len++] = r->inode;
6792                                 }
6793                         }
6794                 }
6795
6796                 /*
6797                  * Report the inode that we are working on
6798                  */
6799                 pctx.inode = &p->inode;
6800                 pctx.ino = ino;
6801                 pctx.dir = p->dir;
6802                 pctx.blkcount = p->num_dupblocks;
6803                 pctx.num = meta_data ? shared_len+1 : shared_len;
6804                 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
6805                 pctx.blkcount = 0;
6806                 pctx.num = 0;
6807
6808                 if (meta_data)
6809                         fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
6810
6811                 for (i = 0; i < shared_len; i++) {
6812                         m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
6813                         if (!m)
6814                                 continue; /* should never happen */
6815                         t = (struct dup_inode *) dnode_get(m);
6816                         /*
6817                          * Report the inode that we are sharing with
6818                          */
6819                         pctx.inode = &t->inode;
6820                         pctx.ino = shared[i];
6821                         pctx.dir = t->dir;
6822                         fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
6823                 }
6824                 if (file_ok) {
6825                         fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
6826                         continue;
6827                 }
6828                 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
6829                         pctx.errcode = clone_file(ctx, ino, p, block_buf);
6830                         if (pctx.errcode)
6831                                 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
6832                         else
6833                                 continue;
6834                 }
6835                 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
6836                         delete_file(ctx, ino, p, block_buf);
6837                 else
6838                         ext2fs_unmark_valid(fs);
6839         }
6840         ext2fs_free_mem(&shared);
6841 }
6842
6843 /*
6844  * Drop the refcount on the dup_block structure, and clear the entry
6845  * in the block_dup_map if appropriate.
6846  */
6847 static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
6848 {
6849         p->num_bad--;
6850         if (p->num_bad <= 0 ||
6851             (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
6852                 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
6853 }
6854
6855 static int delete_file_block(ext2_filsys fs,
6856                              blk_t      *block_nr,
6857                              e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6858                              blk_t ref_block FSCK_ATTR((unused)),
6859                              int ref_offset FSCK_ATTR((unused)),
6860                              void *priv_data)
6861 {
6862         struct process_block_struct_1b *pb;
6863         struct dup_block *p;
6864         dnode_t *n;
6865         e2fsck_t ctx;
6866
6867         pb = (struct process_block_struct_1b *) priv_data;
6868         ctx = pb->ctx;
6869
6870         if (HOLE_BLKADDR(*block_nr))
6871                 return 0;
6872
6873         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
6874                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
6875                 if (n) {
6876                         p = (struct dup_block *) dnode_get(n);
6877                         decrement_badcount(ctx, *block_nr, p);
6878                 } else
6879                         com_err("delete_file_block", 0,
6880                             _("internal error; can't find dup_blk for %d\n"),
6881                                 *block_nr);
6882         } else {
6883                 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6884                 ext2fs_block_alloc_stats(fs, *block_nr, -1);
6885         }
6886
6887         return 0;
6888 }
6889
6890 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
6891                         struct dup_inode *dp, char* block_buf)
6892 {
6893         ext2_filsys fs = ctx->fs;
6894         struct process_block_struct_1b pb;
6895         struct ext2_inode       inode;
6896         struct problem_context  pctx;
6897         unsigned int            count;
6898
6899         clear_problem_context(&pctx);
6900         pctx.ino = pb.ino = ino;
6901         pb.dup_blocks = dp->num_dupblocks;
6902         pb.ctx = ctx;
6903         pctx.str = "delete_file";
6904
6905         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
6906         if (ext2fs_inode_has_valid_blocks(&inode))
6907                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6908                                                      delete_file_block, &pb);
6909         if (pctx.errcode)
6910                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
6911         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6912         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6913         if (ctx->inode_bad_map)
6914                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6915         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6916
6917         /* Inode may have changed by block_iterate, so reread it */
6918         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
6919         inode.i_links_count = 0;
6920         inode.i_dtime = time(0);
6921         if (inode.i_file_acl &&
6922             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6923                 count = 1;
6924                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6925                                                    block_buf, -1, &count);
6926                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6927                         pctx.errcode = 0;
6928                         count = 1;
6929                 }
6930                 if (pctx.errcode) {
6931                         pctx.blk = inode.i_file_acl;
6932                         fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
6933                 }
6934                 /*
6935                  * If the count is zero, then arrange to have the
6936                  * block deleted.  If the block is in the block_dup_map,
6937                  * also call delete_file_block since it will take care
6938                  * of keeping the accounting straight.
6939                  */
6940                 if ((count == 0) ||
6941                     ext2fs_test_block_bitmap(ctx->block_dup_map,
6942                                              inode.i_file_acl))
6943                         delete_file_block(fs, &inode.i_file_acl,
6944                                           BLOCK_COUNT_EXTATTR, 0, 0, &pb);
6945         }
6946         e2fsck_write_inode(ctx, ino, &inode, "delete_file");
6947 }
6948
6949 struct clone_struct {
6950         errcode_t       errcode;
6951         ext2_ino_t      dir;
6952         char    *buf;
6953         e2fsck_t ctx;
6954 };
6955
6956 static int clone_file_block(ext2_filsys fs,
6957                             blk_t       *block_nr,
6958                             e2_blkcnt_t blockcnt,
6959                             blk_t ref_block FSCK_ATTR((unused)),
6960                             int ref_offset FSCK_ATTR((unused)),
6961                             void *priv_data)
6962 {
6963         struct dup_block *p;
6964         blk_t   new_block;
6965         errcode_t       retval;
6966         struct clone_struct *cs = (struct clone_struct *) priv_data;
6967         dnode_t *n;
6968         e2fsck_t ctx;
6969
6970         ctx = cs->ctx;
6971
6972         if (HOLE_BLKADDR(*block_nr))
6973                 return 0;
6974
6975         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
6976                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
6977                 if (n) {
6978                         p = (struct dup_block *) dnode_get(n);
6979                         retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
6980                                                   &new_block);
6981                         if (retval) {
6982                                 cs->errcode = retval;
6983                                 return BLOCK_ABORT;
6984                         }
6985                         if (cs->dir && (blockcnt >= 0)) {
6986                                 retval = ext2fs_set_dir_block(fs->dblist,
6987                                       cs->dir, new_block, blockcnt);
6988                                 if (retval) {
6989                                         cs->errcode = retval;
6990                                         return BLOCK_ABORT;
6991                                 }
6992                         }
6993 #if 0
6994                         printf("Cloning block %u to %u\n", *block_nr,
6995                                new_block);
6996 #endif
6997                         retval = io_channel_read_blk(fs->io, *block_nr, 1,
6998                                                      cs->buf);
6999                         if (retval) {
7000                                 cs->errcode = retval;
7001                                 return BLOCK_ABORT;
7002                         }
7003                         retval = io_channel_write_blk(fs->io, new_block, 1,
7004                                                       cs->buf);
7005                         if (retval) {
7006                                 cs->errcode = retval;
7007                                 return BLOCK_ABORT;
7008                         }
7009                         decrement_badcount(ctx, *block_nr, p);
7010                         *block_nr = new_block;
7011                         ext2fs_mark_block_bitmap(ctx->block_found_map,
7012                                                  new_block);
7013                         ext2fs_mark_block_bitmap(fs->block_map, new_block);
7014                         return BLOCK_CHANGED;
7015                 } else
7016                         com_err("clone_file_block", 0,
7017                             _("internal error; can't find dup_blk for %d\n"),
7018                                 *block_nr);
7019         }
7020         return 0;
7021 }
7022
7023 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
7024                       struct dup_inode *dp, char* block_buf)
7025 {
7026         ext2_filsys fs = ctx->fs;
7027         errcode_t       retval;
7028         struct clone_struct cs;
7029         struct problem_context  pctx;
7030         blk_t           blk;
7031         dnode_t         *n;
7032         struct inode_el *ino_el;
7033         struct dup_block        *db;
7034         struct dup_inode        *di;
7035
7036         clear_problem_context(&pctx);
7037         cs.errcode = 0;
7038         cs.dir = 0;
7039         cs.ctx = ctx;
7040         retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
7041         if (retval)
7042                 return retval;
7043
7044         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
7045                 cs.dir = ino;
7046
7047         pctx.ino = ino;
7048         pctx.str = "clone_file";
7049         if (ext2fs_inode_has_valid_blocks(&dp->inode))
7050                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
7051                                                      clone_file_block, &cs);
7052         ext2fs_mark_bb_dirty(fs);
7053         if (pctx.errcode) {
7054                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
7055                 retval = pctx.errcode;
7056                 goto errout;
7057         }
7058         if (cs.errcode) {
7059                 com_err("clone_file", cs.errcode,
7060                         _("returned from clone_file_block"));
7061                 retval = cs.errcode;
7062                 goto errout;
7063         }
7064         /* The inode may have changed on disk, so we have to re-read it */
7065         e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
7066         blk = dp->inode.i_file_acl;
7067         if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
7068                                      BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
7069                     BLOCK_CHANGED)) {
7070                 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
7071                 /*
7072                  * If we cloned the EA block, find all other inodes
7073                  * which refered to that EA block, and modify
7074                  * them to point to the new EA block.
7075                  */
7076                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
7077                 db = (struct dup_block *) dnode_get(n);
7078                 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
7079                         if (ino_el->inode == ino)
7080                                 continue;
7081                         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
7082                         di = (struct dup_inode *) dnode_get(n);
7083                         if (di->inode.i_file_acl == blk) {
7084                                 di->inode.i_file_acl = dp->inode.i_file_acl;
7085                                 e2fsck_write_inode(ctx, ino_el->inode,
7086                                            &di->inode, "clone file EA");
7087                                 decrement_badcount(ctx, blk, db);
7088                         }
7089                 }
7090         }
7091         retval = 0;
7092 errout:
7093         ext2fs_free_mem(&cs.buf);
7094         return retval;
7095 }
7096
7097 /*
7098  * This routine returns 1 if a block overlaps with one of the superblocks,
7099  * group descriptors, inode bitmaps, or block bitmaps.
7100  */
7101 static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
7102 {
7103         ext2_filsys fs = ctx->fs;
7104         blk_t   block;
7105         dgrp_t  i;
7106
7107         block = fs->super->s_first_data_block;
7108         for (i = 0; i < fs->group_desc_count; i++) {
7109
7110                 /* Check superblocks/block group descriptros */
7111                 if (ext2fs_bg_has_super(fs, i)) {
7112                         if (test_block >= block &&
7113                             (test_block <= block + fs->desc_blocks))
7114                                 return 1;
7115                 }
7116
7117                 /* Check the inode table */
7118                 if ((fs->group_desc[i].bg_inode_table) &&
7119                     (test_block >= fs->group_desc[i].bg_inode_table) &&
7120                     (test_block < (fs->group_desc[i].bg_inode_table +
7121                                    fs->inode_blocks_per_group)))
7122                         return 1;
7123
7124                 /* Check the bitmap blocks */
7125                 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
7126                     (test_block == fs->group_desc[i].bg_inode_bitmap))
7127                         return 1;
7128
7129                 block += fs->super->s_blocks_per_group;
7130         }
7131         return 0;
7132 }
7133 /*
7134  * pass2.c --- check directory structure
7135  *
7136  * Pass 2 of e2fsck iterates through all active directory inodes, and
7137  * applies to following tests to each directory entry in the directory
7138  * blocks in the inodes:
7139  *
7140  *      - The length of the directory entry (rec_len) should be at
7141  *              least 8 bytes, and no more than the remaining space
7142  *              left in the directory block.
7143  *      - The length of the name in the directory entry (name_len)
7144  *              should be less than (rec_len - 8).
7145  *      - The inode number in the directory entry should be within
7146  *              legal bounds.
7147  *      - The inode number should refer to a in-use inode.
7148  *      - The first entry should be '.', and its inode should be
7149  *              the inode of the directory.
7150  *      - The second entry should be '..'.
7151  *
7152  * To minimize disk seek time, the directory blocks are processed in
7153  * sorted order of block numbers.
7154  *
7155  * Pass 2 also collects the following information:
7156  *      - The inode numbers of the subdirectories for each directory.
7157  *
7158  * Pass 2 relies on the following information from previous passes:
7159  *      - The directory information collected in pass 1.
7160  *      - The inode_used_map bitmap
7161  *      - The inode_bad_map bitmap
7162  *      - The inode_dir_map bitmap
7163  *
7164  * Pass 2 frees the following data structures
7165  *      - The inode_bad_map bitmap
7166  *      - The inode_reg_map bitmap
7167  */
7168
7169 /* #define DX_DEBUG */
7170
7171 /*
7172  * Keeps track of how many times an inode is referenced.
7173  */
7174 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
7175 static int check_dir_block(ext2_filsys fs,
7176                            struct ext2_db_entry *dir_blocks_info,
7177                            void *priv_data);
7178 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
7179                               struct problem_context *pctx);
7180 static int update_dir_block(ext2_filsys fs,
7181                             blk_t       *block_nr,
7182                             e2_blkcnt_t blockcnt,
7183                             blk_t       ref_block,
7184                             int         ref_offset,
7185                             void        *priv_data);
7186 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
7187 static int htree_depth(struct dx_dir_info *dx_dir,
7188                        struct dx_dirblock_info *dx_db);
7189 static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b);
7190
7191 struct check_dir_struct {
7192         char *buf;
7193         struct problem_context  pctx;
7194         int     count, max;
7195         e2fsck_t ctx;
7196 };
7197
7198 static void e2fsck_pass2(e2fsck_t ctx)
7199 {
7200         struct ext2_super_block *sb = ctx->fs->super;
7201         struct problem_context  pctx;
7202         ext2_filsys             fs = ctx->fs;
7203         char                    *buf;
7204 #ifdef RESOURCE_TRACK
7205         struct resource_track   rtrack;
7206 #endif
7207         struct dir_info         *dir;
7208         struct check_dir_struct cd;
7209         struct dx_dir_info      *dx_dir;
7210         struct dx_dirblock_info *dx_db, *dx_parent;
7211         int                     b;
7212         int                     i, depth;
7213         problem_t               code;
7214         int                     bad_dir;
7215
7216 #ifdef RESOURCE_TRACK
7217         init_resource_track(&rtrack);
7218 #endif
7219
7220         clear_problem_context(&cd.pctx);
7221
7222 #ifdef MTRACE
7223         mtrace_print("Pass 2");
7224 #endif
7225
7226         if (!(ctx->options & E2F_OPT_PREEN))
7227                 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
7228
7229         cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
7230                                                 0, ctx->inode_link_info,
7231                                                 &ctx->inode_count);
7232         if (cd.pctx.errcode) {
7233                 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
7234                 ctx->flags |= E2F_FLAG_ABORT;
7235                 return;
7236         }
7237         buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
7238                                               "directory scan buffer");
7239
7240         /*
7241          * Set up the parent pointer for the root directory, if
7242          * present.  (If the root directory is not present, we will
7243          * create it in pass 3.)
7244          */
7245         dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
7246         if (dir)
7247                 dir->parent = EXT2_ROOT_INO;
7248
7249         cd.buf = buf;
7250         cd.ctx = ctx;
7251         cd.count = 1;
7252         cd.max = ext2fs_dblist_count(fs->dblist);
7253
7254         if (ctx->progress)
7255                 (void) (ctx->progress)(ctx, 2, 0, cd.max);
7256
7257         if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
7258                 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
7259
7260         cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
7261                                                 &cd);
7262         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7263                 return;
7264         if (cd.pctx.errcode) {
7265                 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
7266                 ctx->flags |= E2F_FLAG_ABORT;
7267                 return;
7268         }
7269
7270 #ifdef ENABLE_HTREE
7271         for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
7272                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7273                         return;
7274                 if (dx_dir->numblocks == 0)
7275                         continue;
7276                 clear_problem_context(&pctx);
7277                 bad_dir = 0;
7278                 pctx.dir = dx_dir->ino;
7279                 dx_db = dx_dir->dx_block;
7280                 if (dx_db->flags & DX_FLAG_REFERENCED)
7281                         dx_db->flags |= DX_FLAG_DUP_REF;
7282                 else
7283                         dx_db->flags |= DX_FLAG_REFERENCED;
7284                 /*
7285                  * Find all of the first and last leaf blocks, and
7286                  * update their parent's min and max hash values
7287                  */
7288                 for (b=0, dx_db = dx_dir->dx_block;
7289                      b < dx_dir->numblocks;
7290                      b++, dx_db++) {
7291                         if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
7292                             !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
7293                                 continue;
7294                         dx_parent = &dx_dir->dx_block[dx_db->parent];
7295                         /*
7296                          * XXX Make sure dx_parent->min_hash > dx_db->min_hash
7297                          */
7298                         if (dx_db->flags & DX_FLAG_FIRST)
7299                                 dx_parent->min_hash = dx_db->min_hash;
7300                         /*
7301                          * XXX Make sure dx_parent->max_hash < dx_db->max_hash
7302                          */
7303                         if (dx_db->flags & DX_FLAG_LAST)
7304                                 dx_parent->max_hash = dx_db->max_hash;
7305                 }
7306
7307                 for (b=0, dx_db = dx_dir->dx_block;
7308                      b < dx_dir->numblocks;
7309                      b++, dx_db++) {
7310                         pctx.blkcount = b;
7311                         pctx.group = dx_db->parent;
7312                         code = 0;
7313                         if (!(dx_db->flags & DX_FLAG_FIRST) &&
7314                             (dx_db->min_hash < dx_db->node_min_hash)) {
7315                                 pctx.blk = dx_db->min_hash;
7316                                 pctx.blk2 = dx_db->node_min_hash;
7317                                 code = PR_2_HTREE_MIN_HASH;
7318                                 fix_problem(ctx, code, &pctx);
7319                                 bad_dir++;
7320                         }
7321                         if (dx_db->type == DX_DIRBLOCK_LEAF) {
7322                                 depth = htree_depth(dx_dir, dx_db);
7323                                 if (depth != dx_dir->depth) {
7324                                         code = PR_2_HTREE_BAD_DEPTH;
7325                                         fix_problem(ctx, code, &pctx);
7326                                         bad_dir++;
7327                                 }
7328                         }
7329                         /*
7330                          * This test doesn't apply for the root block
7331                          * at block #0
7332                          */
7333                         if (b &&
7334                             (dx_db->max_hash > dx_db->node_max_hash)) {
7335                                 pctx.blk = dx_db->max_hash;
7336                                 pctx.blk2 = dx_db->node_max_hash;
7337                                 code = PR_2_HTREE_MAX_HASH;
7338                                 fix_problem(ctx, code, &pctx);
7339                                 bad_dir++;
7340                         }
7341                         if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
7342                                 code = PR_2_HTREE_NOTREF;
7343                                 fix_problem(ctx, code, &pctx);
7344                                 bad_dir++;
7345                         } else if (dx_db->flags & DX_FLAG_DUP_REF) {
7346                                 code = PR_2_HTREE_DUPREF;
7347                                 fix_problem(ctx, code, &pctx);
7348                                 bad_dir++;
7349                         }
7350                         if (code == 0)
7351                                 continue;
7352                 }
7353                 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
7354                         clear_htree(ctx, dx_dir->ino);
7355                         dx_dir->numblocks = 0;
7356                 }
7357         }
7358 #endif
7359         ext2fs_free_mem(&buf);
7360         ext2fs_free_dblist(fs->dblist);
7361
7362         if (ctx->inode_bad_map) {
7363                 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
7364                 ctx->inode_bad_map = 0;
7365         }
7366         if (ctx->inode_reg_map) {
7367                 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
7368                 ctx->inode_reg_map = 0;
7369         }
7370
7371         clear_problem_context(&pctx);
7372         if (ctx->large_files) {
7373                 if (!(sb->s_feature_ro_compat &
7374                       EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
7375                     fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
7376                         sb->s_feature_ro_compat |=
7377                                 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
7378                         ext2fs_mark_super_dirty(fs);
7379                 }
7380                 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
7381                     fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
7382                         ext2fs_update_dynamic_rev(fs);
7383                         ext2fs_mark_super_dirty(fs);
7384                 }
7385         } else if (!ctx->large_files &&
7386             (sb->s_feature_ro_compat &
7387               EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
7388                 if (fs->flags & EXT2_FLAG_RW) {
7389                         sb->s_feature_ro_compat &=
7390                                 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
7391                         ext2fs_mark_super_dirty(fs);
7392                 }
7393         }
7394
7395 #ifdef RESOURCE_TRACK
7396         if (ctx->options & E2F_OPT_TIME2) {
7397                 e2fsck_clear_progbar(ctx);
7398                 print_resource_track(_("Pass 2"), &rtrack);
7399         }
7400 #endif
7401 }
7402
7403 #define MAX_DEPTH 32000
7404 static int htree_depth(struct dx_dir_info *dx_dir,
7405                        struct dx_dirblock_info *dx_db)
7406 {
7407         int     depth = 0;
7408
7409         while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
7410                 dx_db = &dx_dir->dx_block[dx_db->parent];
7411                 depth++;
7412         }
7413         return depth;
7414 }
7415
7416 static int dict_de_cmp(const void *a, const void *b)
7417 {
7418         const struct ext2_dir_entry *de_a, *de_b;
7419         int     a_len, b_len;
7420
7421         de_a = (const struct ext2_dir_entry *) a;
7422         a_len = de_a->name_len & 0xFF;
7423         de_b = (const struct ext2_dir_entry *) b;
7424         b_len = de_b->name_len & 0xFF;
7425
7426         if (a_len != b_len)
7427                 return (a_len - b_len);
7428
7429         return strncmp(de_a->name, de_b->name, a_len);
7430 }
7431
7432 /*
7433  * This is special sort function that makes sure that directory blocks
7434  * with a dirblock of zero are sorted to the beginning of the list.
7435  * This guarantees that the root node of the htree directories are
7436  * processed first, so we know what hash version to use.
7437  */
7438 static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b)
7439 {
7440         const struct ext2_db_entry *db_a =
7441                 (const struct ext2_db_entry *) a;
7442         const struct ext2_db_entry *db_b =
7443                 (const struct ext2_db_entry *) b;
7444
7445         if (db_a->blockcnt && !db_b->blockcnt)
7446                 return 1;
7447
7448         if (!db_a->blockcnt && db_b->blockcnt)
7449                 return -1;
7450
7451         if (db_a->blk != db_b->blk)
7452                 return (int) (db_a->blk - db_b->blk);
7453
7454         if (db_a->ino != db_b->ino)
7455                 return (int) (db_a->ino - db_b->ino);
7456
7457         return (int) (db_a->blockcnt - db_b->blockcnt);
7458 }
7459
7460
7461 /*
7462  * Make sure the first entry in the directory is '.', and that the
7463  * directory entry is sane.
7464  */
7465 static int check_dot(e2fsck_t ctx,
7466                      struct ext2_dir_entry *dirent,
7467                      ext2_ino_t ino, struct problem_context *pctx)
7468 {
7469         struct ext2_dir_entry *nextdir;
7470         int     status = 0;
7471         int     created = 0;
7472         int     new_len;
7473         int     problem = 0;
7474
7475         if (!dirent->inode)
7476                 problem = PR_2_MISSING_DOT;
7477         else if (((dirent->name_len & 0xFF) != 1) ||
7478                  (dirent->name[0] != '.'))
7479                 problem = PR_2_1ST_NOT_DOT;
7480         else if (dirent->name[1] != '\0')
7481                 problem = PR_2_DOT_NULL_TERM;
7482
7483         if (problem) {
7484                 if (fix_problem(ctx, problem, pctx)) {
7485                         if (dirent->rec_len < 12)
7486                                 dirent->rec_len = 12;
7487                         dirent->inode = ino;
7488                         dirent->name_len = 1;
7489                         dirent->name[0] = '.';
7490                         dirent->name[1] = '\0';
7491                         status = 1;
7492                         created = 1;
7493                 }
7494         }
7495         if (dirent->inode != ino) {
7496                 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
7497                         dirent->inode = ino;
7498                         status = 1;
7499                 }
7500         }
7501         if (dirent->rec_len > 12) {
7502                 new_len = dirent->rec_len - 12;
7503                 if (new_len > 12) {
7504                         if (created ||
7505                             fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
7506                                 nextdir = (struct ext2_dir_entry *)
7507                                         ((char *) dirent + 12);
7508                                 dirent->rec_len = 12;
7509                                 nextdir->rec_len = new_len;
7510                                 nextdir->inode = 0;
7511                                 nextdir->name_len = 0;
7512                                 status = 1;
7513                         }
7514                 }
7515         }
7516         return status;
7517 }
7518
7519 /*
7520  * Make sure the second entry in the directory is '..', and that the
7521  * directory entry is sane.  We do not check the inode number of '..'
7522  * here; this gets done in pass 3.
7523  */
7524 static int check_dotdot(e2fsck_t ctx,
7525                         struct ext2_dir_entry *dirent,
7526                         struct dir_info *dir, struct problem_context *pctx)
7527 {
7528         int             problem = 0;
7529
7530         if (!dirent->inode)
7531                 problem = PR_2_MISSING_DOT_DOT;
7532         else if (((dirent->name_len & 0xFF) != 2) ||
7533                  (dirent->name[0] != '.') ||
7534                  (dirent->name[1] != '.'))
7535                 problem = PR_2_2ND_NOT_DOT_DOT;
7536         else if (dirent->name[2] != '\0')
7537                 problem = PR_2_DOT_DOT_NULL_TERM;
7538
7539         if (problem) {
7540                 if (fix_problem(ctx, problem, pctx)) {
7541                         if (dirent->rec_len < 12)
7542                                 dirent->rec_len = 12;
7543                         /*
7544                          * Note: we don't have the parent inode just
7545                          * yet, so we will fill it in with the root
7546                          * inode.  This will get fixed in pass 3.
7547                          */
7548                         dirent->inode = EXT2_ROOT_INO;
7549                         dirent->name_len = 2;
7550                         dirent->name[0] = '.';
7551                         dirent->name[1] = '.';
7552                         dirent->name[2] = '\0';
7553                         return 1;
7554                 }
7555                 return 0;
7556         }
7557         dir->dotdot = dirent->inode;
7558         return 0;
7559 }
7560
7561 /*
7562  * Check to make sure a directory entry doesn't contain any illegal
7563  * characters.
7564  */
7565 static int check_name(e2fsck_t ctx,
7566                       struct ext2_dir_entry *dirent,
7567                       struct problem_context *pctx)
7568 {
7569         int     i;
7570         int     fixup = -1;
7571         int     ret = 0;
7572
7573         for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
7574                 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
7575                         if (fixup < 0) {
7576                                 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
7577                         }
7578                         if (fixup) {
7579                                 dirent->name[i] = '.';
7580                                 ret = 1;
7581                         }
7582                 }
7583         }
7584         return ret;
7585 }
7586
7587 /*
7588  * Check the directory filetype (if present)
7589  */
7590
7591 /*
7592  * Given a mode, return the ext2 file type
7593  */
7594 static int ext2_file_type(unsigned int mode)
7595 {
7596         if (LINUX_S_ISREG(mode))
7597                 return EXT2_FT_REG_FILE;
7598
7599         if (LINUX_S_ISDIR(mode))
7600                 return EXT2_FT_DIR;
7601
7602         if (LINUX_S_ISCHR(mode))
7603                 return EXT2_FT_CHRDEV;
7604
7605         if (LINUX_S_ISBLK(mode))
7606                 return EXT2_FT_BLKDEV;
7607
7608         if (LINUX_S_ISLNK(mode))
7609                 return EXT2_FT_SYMLINK;
7610
7611         if (LINUX_S_ISFIFO(mode))
7612                 return EXT2_FT_FIFO;
7613
7614         if (LINUX_S_ISSOCK(mode))
7615                 return EXT2_FT_SOCK;
7616
7617         return 0;
7618 }
7619
7620 static _INLINE_ int check_filetype(e2fsck_t ctx,
7621                                    struct ext2_dir_entry *dirent,
7622                                    struct problem_context *pctx)
7623 {
7624         int     filetype = dirent->name_len >> 8;
7625         int     should_be = EXT2_FT_UNKNOWN;
7626         struct ext2_inode       inode;
7627
7628         if (!(ctx->fs->super->s_feature_incompat &
7629               EXT2_FEATURE_INCOMPAT_FILETYPE)) {
7630                 if (filetype == 0 ||
7631                     !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
7632                         return 0;
7633                 dirent->name_len = dirent->name_len & 0xFF;
7634                 return 1;
7635         }
7636
7637         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
7638                 should_be = EXT2_FT_DIR;
7639         } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
7640                                             dirent->inode)) {
7641                 should_be = EXT2_FT_REG_FILE;
7642         } else if (ctx->inode_bad_map &&
7643                    ext2fs_test_inode_bitmap(ctx->inode_bad_map,
7644                                             dirent->inode))
7645                 should_be = 0;
7646         else {
7647                 e2fsck_read_inode(ctx, dirent->inode, &inode,
7648                                   "check_filetype");
7649                 should_be = ext2_file_type(inode.i_mode);
7650         }
7651         if (filetype == should_be)
7652                 return 0;
7653         pctx->num = should_be;
7654
7655         if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
7656                         pctx) == 0)
7657                 return 0;
7658
7659         dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
7660         return 1;
7661 }
7662
7663 #ifdef ENABLE_HTREE
7664 static void parse_int_node(ext2_filsys fs,
7665                            struct ext2_db_entry *db,
7666                            struct check_dir_struct *cd,
7667                            struct dx_dir_info   *dx_dir,
7668                            char *block_buf)
7669 {
7670         struct          ext2_dx_root_info  *root;
7671         struct          ext2_dx_entry *ent;
7672         struct          ext2_dx_countlimit *limit;
7673         struct dx_dirblock_info *dx_db;
7674         int             i, expect_limit, count;
7675         blk_t           blk;
7676         ext2_dirhash_t  min_hash = 0xffffffff;
7677         ext2_dirhash_t  max_hash = 0;
7678         ext2_dirhash_t  hash = 0, prev_hash;
7679
7680         if (db->blockcnt == 0) {
7681                 root = (struct ext2_dx_root_info *) (block_buf + 24);
7682
7683 #ifdef DX_DEBUG
7684                 printf("Root node dump:\n");
7685                 printf("\t Reserved zero: %d\n", root->reserved_zero);
7686                 printf("\t Hash Version: %d\n", root->hash_version);
7687                 printf("\t Info length: %d\n", root->info_length);
7688                 printf("\t Indirect levels: %d\n", root->indirect_levels);
7689                 printf("\t Flags: %d\n", root->unused_flags);
7690 #endif
7691
7692                 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
7693         } else {
7694                 ent = (struct ext2_dx_entry *) (block_buf+8);
7695         }
7696         limit = (struct ext2_dx_countlimit *) ent;
7697
7698 #ifdef DX_DEBUG
7699         printf("Number of entries (count): %d\n",
7700                ext2fs_le16_to_cpu(limit->count));
7701         printf("Number of entries (limit): %d\n",
7702                ext2fs_le16_to_cpu(limit->limit));
7703 #endif
7704
7705         count = ext2fs_le16_to_cpu(limit->count);
7706         expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
7707                 sizeof(struct ext2_dx_entry);
7708         if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
7709                 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
7710                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
7711                         goto clear_and_exit;
7712         }
7713         if (count > expect_limit) {
7714                 cd->pctx.num = count;
7715                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
7716                         goto clear_and_exit;
7717                 count = expect_limit;
7718         }
7719
7720         for (i=0; i < count; i++) {
7721                 prev_hash = hash;
7722                 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
7723 #ifdef DX_DEBUG
7724                 printf("Entry #%d: Hash 0x%08x, block %d\n", i,
7725                        hash, ext2fs_le32_to_cpu(ent[i].block));
7726 #endif
7727                 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
7728                 /* Check to make sure the block is valid */
7729                 if (blk > (blk_t) dx_dir->numblocks) {
7730                         cd->pctx.blk = blk;
7731                         if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
7732                                         &cd->pctx))
7733                                 goto clear_and_exit;
7734                 }
7735                 if (hash < prev_hash &&
7736                     fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
7737                         goto clear_and_exit;
7738                 dx_db = &dx_dir->dx_block[blk];
7739                 if (dx_db->flags & DX_FLAG_REFERENCED) {
7740                         dx_db->flags |= DX_FLAG_DUP_REF;
7741                 } else {
7742                         dx_db->flags |= DX_FLAG_REFERENCED;
7743                         dx_db->parent = db->blockcnt;
7744                 }
7745                 if (hash < min_hash)
7746                         min_hash = hash;
7747                 if (hash > max_hash)
7748                         max_hash = hash;
7749                 dx_db->node_min_hash = hash;
7750                 if ((i+1) < count)
7751                         dx_db->node_max_hash =
7752                           ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
7753                 else {
7754                         dx_db->node_max_hash = 0xfffffffe;
7755                         dx_db->flags |= DX_FLAG_LAST;
7756                 }
7757                 if (i == 0)
7758                         dx_db->flags |= DX_FLAG_FIRST;
7759         }
7760 #ifdef DX_DEBUG
7761         printf("Blockcnt = %d, min hash 0x%08x, max hash 0x%08x\n",
7762                db->blockcnt, min_hash, max_hash);
7763 #endif
7764         dx_db = &dx_dir->dx_block[db->blockcnt];
7765         dx_db->min_hash = min_hash;
7766         dx_db->max_hash = max_hash;
7767         return;
7768
7769 clear_and_exit:
7770         clear_htree(cd->ctx, cd->pctx.ino);
7771         dx_dir->numblocks = 0;
7772 }
7773 #endif /* ENABLE_HTREE */
7774
7775 /*
7776  * Given a busted directory, try to salvage it somehow.
7777  *
7778  */
7779 static void salvage_directory(ext2_filsys fs,
7780                               struct ext2_dir_entry *dirent,
7781                               struct ext2_dir_entry *prev,
7782                               unsigned int *offset)
7783 {
7784         char    *cp = (char *) dirent;
7785         int left = fs->blocksize - *offset - dirent->rec_len;
7786         int name_len = dirent->name_len & 0xFF;
7787
7788         /*
7789          * Special case of directory entry of size 8: copy what's left
7790          * of the directory block up to cover up the invalid hole.
7791          */
7792         if ((left >= 12) && (dirent->rec_len == 8)) {
7793                 memmove(cp, cp+8, left);
7794                 memset(cp + left, 0, 8);
7795                 return;
7796         }
7797         /*
7798          * If the directory entry overruns the end of the directory
7799          * block, and the name is small enough to fit, then adjust the
7800          * record length.
7801          */
7802         if ((left < 0) &&
7803             (name_len + 8 <= dirent->rec_len + left) &&
7804             dirent->inode <= fs->super->s_inodes_count &&
7805             strnlen(dirent->name, name_len) == name_len) {
7806                 dirent->rec_len += left;
7807                 return;
7808         }
7809         /*
7810          * If the directory entry is a multiple of four, so it is
7811          * valid, let the previous directory entry absorb the invalid
7812          * one.
7813          */
7814         if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
7815                 prev->rec_len += dirent->rec_len;
7816                 *offset += dirent->rec_len;
7817                 return;
7818         }
7819         /*
7820          * Default salvage method --- kill all of the directory
7821          * entries for the rest of the block.  We will either try to
7822          * absorb it into the previous directory entry, or create a
7823          * new empty directory entry the rest of the directory block.
7824          */
7825         if (prev) {
7826                 prev->rec_len += fs->blocksize - *offset;
7827                 *offset = fs->blocksize;
7828         } else {
7829                 dirent->rec_len = fs->blocksize - *offset;
7830                 dirent->name_len = 0;
7831                 dirent->inode = 0;
7832         }
7833 }
7834
7835 static int check_dir_block(ext2_filsys fs,
7836                            struct ext2_db_entry *db,
7837                            void *priv_data)
7838 {
7839         struct dir_info         *subdir, *dir;
7840         struct dx_dir_info      *dx_dir;
7841 #ifdef ENABLE_HTREE
7842         struct dx_dirblock_info *dx_db = 0;
7843 #endif /* ENABLE_HTREE */
7844         struct ext2_dir_entry   *dirent, *prev;
7845         ext2_dirhash_t          hash;
7846         unsigned int            offset = 0;
7847         int                     dir_modified = 0;
7848         int                     dot_state;
7849         blk_t                   block_nr = db->blk;
7850         ext2_ino_t              ino = db->ino;
7851         __u16                   links;
7852         struct check_dir_struct *cd;
7853         char                    *buf;
7854         e2fsck_t                ctx;
7855         int                     problem;
7856         struct ext2_dx_root_info *root;
7857         struct ext2_dx_countlimit *limit;
7858         static dict_t de_dict;
7859         struct problem_context  pctx;
7860         int     dups_found = 0;
7861
7862         cd = (struct check_dir_struct *) priv_data;
7863         buf = cd->buf;
7864         ctx = cd->ctx;
7865
7866         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7867                 return DIRENT_ABORT;
7868
7869         if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
7870                 return DIRENT_ABORT;
7871
7872         /*
7873          * Make sure the inode is still in use (could have been
7874          * deleted in the duplicate/bad blocks pass.
7875          */
7876         if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
7877                 return 0;
7878
7879         cd->pctx.ino = ino;
7880         cd->pctx.blk = block_nr;
7881         cd->pctx.blkcount = db->blockcnt;
7882         cd->pctx.ino2 = 0;
7883         cd->pctx.dirent = 0;
7884         cd->pctx.num = 0;
7885
7886         if (db->blk == 0) {
7887                 if (allocate_dir_block(ctx, db, &cd->pctx))
7888                         return 0;
7889                 block_nr = db->blk;
7890         }
7891
7892         if (db->blockcnt)
7893                 dot_state = 2;
7894         else
7895                 dot_state = 0;
7896
7897         if (ctx->dirs_to_hash &&
7898             ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
7899                 dups_found++;
7900
7901 #if 0
7902         printf("In process_dir_block block %lu, #%d, inode %lu\n", block_nr,
7903                db->blockcnt, ino);
7904 #endif
7905
7906         cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
7907         if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
7908                 cd->pctx.errcode = 0; /* We'll handle this ourselves */
7909         if (cd->pctx.errcode) {
7910                 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
7911                         ctx->flags |= E2F_FLAG_ABORT;
7912                         return DIRENT_ABORT;
7913                 }
7914                 memset(buf, 0, fs->blocksize);
7915         }
7916 #ifdef ENABLE_HTREE
7917         dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
7918         if (dx_dir && dx_dir->numblocks) {
7919                 if (db->blockcnt >= dx_dir->numblocks) {
7920                         printf("XXX should never happen!!!\n");
7921                         abort();
7922                 }
7923                 dx_db = &dx_dir->dx_block[db->blockcnt];
7924                 dx_db->type = DX_DIRBLOCK_LEAF;
7925                 dx_db->phys = block_nr;
7926                 dx_db->min_hash = ~0;
7927                 dx_db->max_hash = 0;
7928
7929                 dirent = (struct ext2_dir_entry *) buf;
7930                 limit = (struct ext2_dx_countlimit *) (buf+8);
7931                 if (db->blockcnt == 0) {
7932                         root = (struct ext2_dx_root_info *) (buf + 24);
7933                         dx_db->type = DX_DIRBLOCK_ROOT;
7934                         dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
7935                         if ((root->reserved_zero ||
7936                              root->info_length < 8 ||
7937                              root->indirect_levels > 1) &&
7938                             fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
7939                                 clear_htree(ctx, ino);
7940                                 dx_dir->numblocks = 0;
7941                                 dx_db = 0;
7942                         }
7943                         dx_dir->hashversion = root->hash_version;
7944                         dx_dir->depth = root->indirect_levels + 1;
7945                 } else if ((dirent->inode == 0) &&
7946                            (dirent->rec_len == fs->blocksize) &&
7947                            (dirent->name_len == 0) &&
7948                            (ext2fs_le16_to_cpu(limit->limit) ==
7949                             ((fs->blocksize-8) /
7950                              sizeof(struct ext2_dx_entry))))
7951                         dx_db->type = DX_DIRBLOCK_NODE;
7952         }
7953 #endif /* ENABLE_HTREE */
7954
7955         dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
7956         prev = 0;
7957         do {
7958                 problem = 0;
7959                 dirent = (struct ext2_dir_entry *) (buf + offset);
7960                 cd->pctx.dirent = dirent;
7961                 cd->pctx.num = offset;
7962                 if (((offset + dirent->rec_len) > fs->blocksize) ||
7963                     (dirent->rec_len < 12) ||
7964                     ((dirent->rec_len % 4) != 0) ||
7965                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
7966                         if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
7967                                 salvage_directory(fs, dirent, prev, &offset);
7968                                 dir_modified++;
7969                                 continue;
7970                         } else
7971                                 goto abort_free_dict;
7972                 }
7973                 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
7974                         if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
7975                                 dirent->name_len = EXT2_NAME_LEN;
7976                                 dir_modified++;
7977                         }
7978                 }
7979
7980                 if (dot_state == 0) {
7981                         if (check_dot(ctx, dirent, ino, &cd->pctx))
7982                                 dir_modified++;
7983                 } else if (dot_state == 1) {
7984                         dir = e2fsck_get_dir_info(ctx, ino);
7985                         if (!dir) {
7986                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
7987                                 goto abort_free_dict;
7988                         }
7989                         if (check_dotdot(ctx, dirent, dir, &cd->pctx))
7990                                 dir_modified++;
7991                 } else if (dirent->inode == ino) {
7992                         problem = PR_2_LINK_DOT;
7993                         if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
7994                                 dirent->inode = 0;
7995                                 dir_modified++;
7996                                 goto next;
7997                         }
7998                 }
7999                 if (!dirent->inode)
8000                         goto next;
8001
8002                 /*
8003                  * Make sure the inode listed is a legal one.
8004                  */
8005                 if (((dirent->inode != EXT2_ROOT_INO) &&
8006                      (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
8007                     (dirent->inode > fs->super->s_inodes_count)) {
8008                         problem = PR_2_BAD_INO;
8009                 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
8010                                                dirent->inode))) {
8011                         /*
8012                          * If the inode is unused, offer to clear it.
8013                          */
8014                         problem = PR_2_UNUSED_INODE;
8015                 } else if (ctx->inode_bb_map &&
8016                            (ext2fs_test_inode_bitmap(ctx->inode_bb_map,
8017                                                      dirent->inode))) {
8018                         /*
8019                          * If the inode is in a bad block, offer to
8020                          * clear it.
8021                          */
8022                         problem = PR_2_BB_INODE;
8023                 } else if ((dot_state > 1) &&
8024                            ((dirent->name_len & 0xFF) == 1) &&
8025                            (dirent->name[0] == '.')) {
8026                         /*
8027                          * If there's a '.' entry in anything other
8028                          * than the first directory entry, it's a
8029                          * duplicate entry that should be removed.
8030                          */
8031                         problem = PR_2_DUP_DOT;
8032                 } else if ((dot_state > 1) &&
8033                            ((dirent->name_len & 0xFF) == 2) &&
8034                            (dirent->name[0] == '.') &&
8035                            (dirent->name[1] == '.')) {
8036                         /*
8037                          * If there's a '..' entry in anything other
8038                          * than the second directory entry, it's a
8039                          * duplicate entry that should be removed.
8040                          */
8041                         problem = PR_2_DUP_DOT_DOT;
8042                 } else if ((dot_state > 1) &&
8043                            (dirent->inode == EXT2_ROOT_INO)) {
8044                         /*
8045                          * Don't allow links to the root directory.
8046                          * We check this specially to make sure we
8047                          * catch this error case even if the root
8048                          * directory hasn't been created yet.
8049                          */
8050                         problem = PR_2_LINK_ROOT;
8051                 } else if ((dot_state > 1) &&
8052                            (dirent->name_len & 0xFF) == 0) {
8053                         /*
8054                          * Don't allow zero-length directory names.
8055                          */
8056                         problem = PR_2_NULL_NAME;
8057                 }
8058
8059                 if (problem) {
8060                         if (fix_problem(ctx, problem, &cd->pctx)) {
8061                                 dirent->inode = 0;
8062                                 dir_modified++;
8063                                 goto next;
8064                         } else {
8065                                 ext2fs_unmark_valid(fs);
8066                                 if (problem == PR_2_BAD_INO)
8067                                         goto next;
8068                         }
8069                 }
8070
8071                 /*
8072                  * If the inode was marked as having bad fields in
8073                  * pass1, process it and offer to fix/clear it.
8074                  * (We wait until now so that we can display the
8075                  * pathname to the user.)
8076                  */
8077                 if (ctx->inode_bad_map &&
8078                     ext2fs_test_inode_bitmap(ctx->inode_bad_map,
8079                                              dirent->inode)) {
8080                         if (e2fsck_process_bad_inode(ctx, ino,
8081                                                      dirent->inode,
8082                                                      buf + fs->blocksize)) {
8083                                 dirent->inode = 0;
8084                                 dir_modified++;
8085                                 goto next;
8086                         }
8087                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8088                                 return DIRENT_ABORT;
8089                 }
8090
8091                 if (check_name(ctx, dirent, &cd->pctx))
8092                         dir_modified++;
8093
8094                 if (check_filetype(ctx, dirent, &cd->pctx))
8095                         dir_modified++;
8096
8097 #ifdef ENABLE_HTREE
8098                 if (dx_db) {
8099                         ext2fs_dirhash(dx_dir->hashversion, dirent->name,
8100                                        (dirent->name_len & 0xFF),
8101                                        fs->super->s_hash_seed, &hash, 0);
8102                         if (hash < dx_db->min_hash)
8103                                 dx_db->min_hash = hash;
8104                         if (hash > dx_db->max_hash)
8105                                 dx_db->max_hash = hash;
8106                 }
8107 #endif
8108
8109                 /*
8110                  * If this is a directory, then mark its parent in its
8111                  * dir_info structure.  If the parent field is already
8112                  * filled in, then this directory has more than one
8113                  * hard link.  We assume the first link is correct,
8114                  * and ask the user if he/she wants to clear this one.
8115                  */
8116                 if ((dot_state > 1) &&
8117                     (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
8118                                               dirent->inode))) {
8119                         subdir = e2fsck_get_dir_info(ctx, dirent->inode);
8120                         if (!subdir) {
8121                                 cd->pctx.ino = dirent->inode;
8122                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
8123                                 goto abort_free_dict;
8124                         }
8125                         if (subdir->parent) {
8126                                 cd->pctx.ino2 = subdir->parent;
8127                                 if (fix_problem(ctx, PR_2_LINK_DIR,
8128                                                 &cd->pctx)) {
8129                                         dirent->inode = 0;
8130                                         dir_modified++;
8131                                         goto next;
8132                                 }
8133                                 cd->pctx.ino2 = 0;
8134                         } else
8135                                 subdir->parent = ino;
8136                 }
8137
8138                 if (dups_found) {
8139                         ;
8140                 } else if (dict_lookup(&de_dict, dirent)) {
8141                         clear_problem_context(&pctx);
8142                         pctx.ino = ino;
8143                         pctx.dirent = dirent;
8144                         fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
8145                         if (!ctx->dirs_to_hash)
8146                                 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
8147                         if (ctx->dirs_to_hash)
8148                                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
8149                         dups_found++;
8150                 } else
8151                         dict_alloc_insert(&de_dict, dirent, dirent);
8152
8153                 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
8154                                         &links);
8155                 if (links > 1)
8156                         ctx->fs_links_count++;
8157                 ctx->fs_total_count++;
8158         next:
8159                 prev = dirent;
8160                 offset += dirent->rec_len;
8161                 dot_state++;
8162         } while (offset < fs->blocksize);
8163 #if 0
8164         printf("\n");
8165 #endif
8166 #ifdef ENABLE_HTREE
8167         if (dx_db) {
8168 #ifdef DX_DEBUG
8169                 printf("db_block %d, type %d, min_hash 0x%0x, max_hash 0x%0x\n",
8170                        db->blockcnt, dx_db->type,
8171                        dx_db->min_hash, dx_db->max_hash);
8172 #endif
8173                 cd->pctx.dir = cd->pctx.ino;
8174                 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
8175                     (dx_db->type == DX_DIRBLOCK_NODE))
8176                         parse_int_node(fs, db, cd, dx_dir, buf);
8177         }
8178 #endif /* ENABLE_HTREE */
8179         if (offset != fs->blocksize) {
8180                 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
8181                 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
8182                         dirent->rec_len = cd->pctx.num;
8183                         dir_modified++;
8184                 }
8185         }
8186         if (dir_modified) {
8187                 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
8188                 if (cd->pctx.errcode) {
8189                         if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
8190                                          &cd->pctx))
8191                                 goto abort_free_dict;
8192                 }
8193                 ext2fs_mark_changed(fs);
8194         }
8195         dict_free_nodes(&de_dict);
8196         return 0;
8197 abort_free_dict:
8198         dict_free_nodes(&de_dict);
8199         ctx->flags |= E2F_FLAG_ABORT;
8200         return DIRENT_ABORT;
8201 }
8202
8203 /*
8204  * This function is called to deallocate a block, and is an interator
8205  * functioned called by deallocate inode via ext2fs_iterate_block().
8206  */
8207 static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
8208                                   e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
8209                                   blk_t ref_block FSCK_ATTR((unused)),
8210                                   int ref_offset FSCK_ATTR((unused)),
8211                                   void *priv_data)
8212 {
8213         e2fsck_t        ctx = (e2fsck_t) priv_data;
8214
8215         if (HOLE_BLKADDR(*block_nr))
8216                 return 0;
8217         if ((*block_nr < fs->super->s_first_data_block) ||
8218             (*block_nr >= fs->super->s_blocks_count))
8219                 return 0;
8220         ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
8221         ext2fs_block_alloc_stats(fs, *block_nr, -1);
8222         return 0;
8223 }
8224
8225 /*
8226  * This fuction deallocates an inode
8227  */
8228 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
8229 {
8230         ext2_filsys fs = ctx->fs;
8231         struct ext2_inode       inode;
8232         struct problem_context  pctx;
8233         __u32                   count;
8234
8235         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
8236         e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
8237         inode.i_links_count = 0;
8238         inode.i_dtime = time(0);
8239         e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
8240         clear_problem_context(&pctx);
8241         pctx.ino = ino;
8242
8243         /*
8244          * Fix up the bitmaps...
8245          */
8246         e2fsck_read_bitmaps(ctx);
8247         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
8248         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
8249         if (ctx->inode_bad_map)
8250                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
8251         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
8252
8253         if (inode.i_file_acl &&
8254             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
8255                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
8256                                                    block_buf, -1, &count);
8257                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
8258                         pctx.errcode = 0;
8259                         count = 1;
8260                 }
8261                 if (pctx.errcode) {
8262                         pctx.blk = inode.i_file_acl;
8263                         fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
8264                         ctx->flags |= E2F_FLAG_ABORT;
8265                         return;
8266                 }
8267                 if (count == 0) {
8268                         ext2fs_unmark_block_bitmap(ctx->block_found_map,
8269                                                    inode.i_file_acl);
8270                         ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
8271                 }
8272                 inode.i_file_acl = 0;
8273         }
8274
8275         if (!ext2fs_inode_has_valid_blocks(&inode))
8276                 return;
8277
8278         if (LINUX_S_ISREG(inode.i_mode) &&
8279             (inode.i_size_high || inode.i_size & 0x80000000UL))
8280                 ctx->large_files--;
8281
8282         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
8283                                             deallocate_inode_block, ctx);
8284         if (pctx.errcode) {
8285                 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
8286                 ctx->flags |= E2F_FLAG_ABORT;
8287                 return;
8288         }
8289 }
8290
8291 /*
8292  * This fuction clears the htree flag on an inode
8293  */
8294 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
8295 {
8296         struct ext2_inode       inode;
8297
8298         e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
8299         inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
8300         e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
8301         if (ctx->dirs_to_hash)
8302                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
8303 }
8304
8305
8306 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
8307                                     ext2_ino_t ino, char *buf)
8308 {
8309         ext2_filsys fs = ctx->fs;
8310         struct ext2_inode       inode;
8311         int                     inode_modified = 0;
8312         int                     not_fixed = 0;
8313         unsigned char           *frag, *fsize;
8314         struct problem_context  pctx;
8315         int     problem = 0;
8316
8317         e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
8318
8319         clear_problem_context(&pctx);
8320         pctx.ino = ino;
8321         pctx.dir = dir;
8322         pctx.inode = &inode;
8323
8324         if (inode.i_file_acl &&
8325             !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
8326             fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
8327                 inode.i_file_acl = 0;
8328 #ifdef EXT2FS_ENABLE_SWAPFS
8329                 /*
8330                  * This is a special kludge to deal with long symlinks
8331                  * on big endian systems.  i_blocks had already been
8332                  * decremented earlier in pass 1, but since i_file_acl
8333                  * hadn't yet been cleared, ext2fs_read_inode()
8334                  * assumed that the file was short symlink and would
8335                  * not have byte swapped i_block[0].  Hence, we have
8336                  * to byte-swap it here.
8337                  */
8338                 if (LINUX_S_ISLNK(inode.i_mode) &&
8339                     (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
8340                     (inode.i_blocks == fs->blocksize >> 9))
8341                         inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
8342 #endif
8343                 inode_modified++;
8344         } else
8345                 not_fixed++;
8346
8347         if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
8348             !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
8349             !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
8350             !(LINUX_S_ISSOCK(inode.i_mode)))
8351                 problem = PR_2_BAD_MODE;
8352         else if (LINUX_S_ISCHR(inode.i_mode)
8353                  && !e2fsck_pass1_check_device_inode(fs, &inode))
8354                 problem = PR_2_BAD_CHAR_DEV;
8355         else if (LINUX_S_ISBLK(inode.i_mode)
8356                  && !e2fsck_pass1_check_device_inode(fs, &inode))
8357                 problem = PR_2_BAD_BLOCK_DEV;
8358         else if (LINUX_S_ISFIFO(inode.i_mode)
8359                  && !e2fsck_pass1_check_device_inode(fs, &inode))
8360                 problem = PR_2_BAD_FIFO;
8361         else if (LINUX_S_ISSOCK(inode.i_mode)
8362                  && !e2fsck_pass1_check_device_inode(fs, &inode))
8363                 problem = PR_2_BAD_SOCKET;
8364         else if (LINUX_S_ISLNK(inode.i_mode)
8365                  && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
8366                 problem = PR_2_INVALID_SYMLINK;
8367         }
8368
8369         if (problem) {
8370                 if (fix_problem(ctx, problem, &pctx)) {
8371                         deallocate_inode(ctx, ino, 0);
8372                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8373                                 return 0;
8374                         return 1;
8375                 } else
8376                         not_fixed++;
8377                 problem = 0;
8378         }
8379
8380         if (inode.i_faddr) {
8381                 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
8382                         inode.i_faddr = 0;
8383                         inode_modified++;
8384                 } else
8385                         not_fixed++;
8386         }
8387
8388         switch (fs->super->s_creator_os) {
8389             case EXT2_OS_LINUX:
8390                 frag = &inode.osd2.linux2.l_i_frag;
8391                 fsize = &inode.osd2.linux2.l_i_fsize;
8392                 break;
8393             case EXT2_OS_HURD:
8394                 frag = &inode.osd2.hurd2.h_i_frag;
8395                 fsize = &inode.osd2.hurd2.h_i_fsize;
8396                 break;
8397             case EXT2_OS_MASIX:
8398                 frag = &inode.osd2.masix2.m_i_frag;
8399                 fsize = &inode.osd2.masix2.m_i_fsize;
8400                 break;
8401             default:
8402                 frag = fsize = 0;
8403         }
8404         if (frag && *frag) {
8405                 pctx.num = *frag;
8406                 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
8407                         *frag = 0;
8408                         inode_modified++;
8409                 } else
8410                         not_fixed++;
8411                 pctx.num = 0;
8412         }
8413         if (fsize && *fsize) {
8414                 pctx.num = *fsize;
8415                 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
8416                         *fsize = 0;
8417                         inode_modified++;
8418                 } else
8419                         not_fixed++;
8420                 pctx.num = 0;
8421         }
8422
8423         if (inode.i_file_acl &&
8424             ((inode.i_file_acl < fs->super->s_first_data_block) ||
8425              (inode.i_file_acl >= fs->super->s_blocks_count))) {
8426                 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
8427                         inode.i_file_acl = 0;
8428                         inode_modified++;
8429                 } else
8430                         not_fixed++;
8431         }
8432         if (inode.i_dir_acl &&
8433             LINUX_S_ISDIR(inode.i_mode)) {
8434                 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
8435                         inode.i_dir_acl = 0;
8436                         inode_modified++;
8437                 } else
8438                         not_fixed++;
8439         }
8440
8441         if (inode_modified)
8442                 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
8443         if (!not_fixed)
8444                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
8445         return 0;
8446 }
8447
8448
8449 /*
8450  * allocate_dir_block --- this function allocates a new directory
8451  *      block for a particular inode; this is done if a directory has
8452  *      a "hole" in it, or if a directory has a illegal block number
8453  *      that was zeroed out and now needs to be replaced.
8454  */
8455 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
8456                               struct problem_context *pctx)
8457 {
8458         ext2_filsys fs = ctx->fs;
8459         blk_t                   blk;
8460         char                    *block;
8461         struct ext2_inode       inode;
8462
8463         if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
8464                 return 1;
8465
8466         /*
8467          * Read the inode and block bitmaps in; we'll be messing with
8468          * them.
8469          */
8470         e2fsck_read_bitmaps(ctx);
8471
8472         /*
8473          * First, find a free block
8474          */
8475         pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8476         if (pctx->errcode) {
8477                 pctx->str = "ext2fs_new_block";
8478                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8479                 return 1;
8480         }
8481         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8482         ext2fs_mark_block_bitmap(fs->block_map, blk);
8483         ext2fs_mark_bb_dirty(fs);
8484
8485         /*
8486          * Now let's create the actual data block for the inode
8487          */
8488         if (db->blockcnt)
8489                 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
8490         else
8491                 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
8492                                                      EXT2_ROOT_INO, &block);
8493
8494         if (pctx->errcode) {
8495                 pctx->str = "ext2fs_new_dir_block";
8496                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8497                 return 1;
8498         }
8499
8500         pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
8501         ext2fs_free_mem(&block);
8502         if (pctx->errcode) {
8503                 pctx->str = "ext2fs_write_dir_block";
8504                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8505                 return 1;
8506         }
8507
8508         /*
8509          * Update the inode block count
8510          */
8511         e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
8512         inode.i_blocks += fs->blocksize / 512;
8513         if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
8514                 inode.i_size = (db->blockcnt+1) * fs->blocksize;
8515         e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
8516
8517         /*
8518          * Finally, update the block pointers for the inode
8519          */
8520         db->blk = blk;
8521         pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
8522                                       0, update_dir_block, db);
8523         if (pctx->errcode) {
8524                 pctx->str = "ext2fs_block_iterate";
8525                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8526                 return 1;
8527         }
8528
8529         return 0;
8530 }
8531
8532 /*
8533  * This is a helper function for allocate_dir_block().
8534  */
8535 static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
8536                             blk_t       *block_nr,
8537                             e2_blkcnt_t blockcnt,
8538                             blk_t ref_block FSCK_ATTR((unused)),
8539                             int ref_offset FSCK_ATTR((unused)),
8540                             void *priv_data)
8541 {
8542         struct ext2_db_entry *db;
8543
8544         db = (struct ext2_db_entry *) priv_data;
8545         if (db->blockcnt == (int) blockcnt) {
8546                 *block_nr = db->blk;
8547                 return BLOCK_CHANGED;
8548         }
8549         return 0;
8550 }
8551
8552 /*
8553  * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
8554  *
8555  * Pass #3 assures that all directories are connected to the
8556  * filesystem tree, using the following algorithm:
8557  *
8558  * First, the root directory is checked to make sure it exists; if
8559  * not, e2fsck will offer to create a new one.  It is then marked as
8560  * "done".
8561  *
8562  * Then, pass3 interates over all directory inodes; for each directory
8563  * it attempts to trace up the filesystem tree, using dirinfo.parent
8564  * until it reaches a directory which has been marked "done".  If it
8565  * can not do so, then the directory must be disconnected, and e2fsck
8566  * will offer to reconnect it to /lost+found.  While it is chasing
8567  * parent pointers up the filesystem tree, if pass3 sees a directory
8568  * twice, then it has detected a filesystem loop, and it will again
8569  * offer to reconnect the directory to /lost+found in to break the
8570  * filesystem loop.
8571  *
8572  * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
8573  * reconnect inodes to /lost+found; this subroutine is also used by
8574  * pass 4.  e2fsck_reconnect_file() calls get_lost_and_found(), which
8575  * is responsible for creating /lost+found if it does not exist.
8576  *
8577  * Pass 3 frees the following data structures:
8578  *      - The dirinfo directory information cache.
8579  */
8580
8581 static void check_root(e2fsck_t ctx);
8582 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
8583                            struct problem_context *pctx);
8584 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
8585
8586 static ext2fs_inode_bitmap inode_loop_detect;
8587 static ext2fs_inode_bitmap inode_done_map;
8588
8589 static void e2fsck_pass3(e2fsck_t ctx)
8590 {
8591         ext2_filsys fs = ctx->fs;
8592         int             i;
8593 #ifdef RESOURCE_TRACK
8594         struct resource_track   rtrack;
8595 #endif
8596         struct problem_context  pctx;
8597         struct dir_info *dir;
8598         unsigned long maxdirs, count;
8599
8600 #ifdef RESOURCE_TRACK
8601         init_resource_track(&rtrack);
8602 #endif
8603
8604         clear_problem_context(&pctx);
8605
8606 #ifdef MTRACE
8607         mtrace_print("Pass 3");
8608 #endif
8609
8610         if (!(ctx->options & E2F_OPT_PREEN))
8611                 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
8612
8613         /*
8614          * Allocate some bitmaps to do loop detection.
8615          */
8616         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
8617                                                     &inode_done_map);
8618         if (pctx.errcode) {
8619                 pctx.num = 2;
8620                 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
8621                 ctx->flags |= E2F_FLAG_ABORT;
8622                 goto abort_exit;
8623         }
8624 #ifdef RESOURCE_TRACK
8625         if (ctx->options & E2F_OPT_TIME) {
8626                 e2fsck_clear_progbar(ctx);
8627                 print_resource_track(_("Peak memory"), &ctx->global_rtrack);
8628         }
8629 #endif
8630
8631         check_root(ctx);
8632         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8633                 goto abort_exit;
8634
8635         ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
8636
8637         maxdirs = e2fsck_get_num_dirinfo(ctx);
8638         count = 1;
8639
8640         if (ctx->progress)
8641                 if ((ctx->progress)(ctx, 3, 0, maxdirs))
8642                         goto abort_exit;
8643
8644         for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
8645                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8646                         goto abort_exit;
8647                 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
8648                         goto abort_exit;
8649                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
8650                         if (check_directory(ctx, dir, &pctx))
8651                                 goto abort_exit;
8652         }
8653
8654         /*
8655          * Force the creation of /lost+found if not present
8656          */
8657         if ((ctx->flags & E2F_OPT_READONLY) == 0)
8658                 e2fsck_get_lost_and_found(ctx, 1);
8659
8660         /*
8661          * If there are any directories that need to be indexed or
8662          * optimized, do it here.
8663          */
8664         e2fsck_rehash_directories(ctx);
8665
8666 abort_exit:
8667         e2fsck_free_dir_info(ctx);
8668         if (inode_loop_detect) {
8669                 ext2fs_free_inode_bitmap(inode_loop_detect);
8670                 inode_loop_detect = 0;
8671         }
8672         if (inode_done_map) {
8673                 ext2fs_free_inode_bitmap(inode_done_map);
8674                 inode_done_map = 0;
8675         }
8676
8677 #ifdef RESOURCE_TRACK
8678         if (ctx->options & E2F_OPT_TIME2) {
8679                 e2fsck_clear_progbar(ctx);
8680                 print_resource_track(_("Pass 3"), &rtrack);
8681         }
8682 #endif
8683 }
8684
8685 /*
8686  * This makes sure the root inode is present; if not, we ask if the
8687  * user wants us to create it.  Not creating it is a fatal error.
8688  */
8689 static void check_root(e2fsck_t ctx)
8690 {
8691         ext2_filsys fs = ctx->fs;
8692         blk_t                   blk;
8693         struct ext2_inode       inode;
8694         char *                  block;
8695         struct problem_context  pctx;
8696
8697         clear_problem_context(&pctx);
8698
8699         if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
8700                 /*
8701                  * If the root inode is not a directory, die here.  The
8702                  * user must have answered 'no' in pass1 when we
8703                  * offered to clear it.
8704                  */
8705                 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
8706                                                EXT2_ROOT_INO))) {
8707                         fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
8708                         ctx->flags |= E2F_FLAG_ABORT;
8709                 }
8710                 return;
8711         }
8712
8713         if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
8714                 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
8715                 ctx->flags |= E2F_FLAG_ABORT;
8716                 return;
8717         }
8718
8719         e2fsck_read_bitmaps(ctx);
8720
8721         /*
8722          * First, find a free block
8723          */
8724         pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8725         if (pctx.errcode) {
8726                 pctx.str = "ext2fs_new_block";
8727                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8728                 ctx->flags |= E2F_FLAG_ABORT;
8729                 return;
8730         }
8731         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8732         ext2fs_mark_block_bitmap(fs->block_map, blk);
8733         ext2fs_mark_bb_dirty(fs);
8734
8735         /*
8736          * Now let's create the actual data block for the inode
8737          */
8738         pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
8739                                             &block);
8740         if (pctx.errcode) {
8741                 pctx.str = "ext2fs_new_dir_block";
8742                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8743                 ctx->flags |= E2F_FLAG_ABORT;
8744                 return;
8745         }
8746
8747         pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
8748         if (pctx.errcode) {
8749                 pctx.str = "ext2fs_write_dir_block";
8750                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8751                 ctx->flags |= E2F_FLAG_ABORT;
8752                 return;
8753         }
8754         ext2fs_free_mem(&block);
8755
8756         /*
8757          * Set up the inode structure
8758          */
8759         memset(&inode, 0, sizeof(inode));
8760         inode.i_mode = 040755;
8761         inode.i_size = fs->blocksize;
8762         inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
8763         inode.i_links_count = 2;
8764         inode.i_blocks = fs->blocksize / 512;
8765         inode.i_block[0] = blk;
8766
8767         /*
8768          * Write out the inode.
8769          */
8770         pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
8771         if (pctx.errcode) {
8772                 pctx.str = "ext2fs_write_inode";
8773                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8774                 ctx->flags |= E2F_FLAG_ABORT;
8775                 return;
8776         }
8777
8778         /*
8779          * Miscellaneous bookkeeping...
8780          */
8781         e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
8782         ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
8783         ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
8784
8785         ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
8786         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
8787         ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
8788         ext2fs_mark_ib_dirty(fs);
8789 }
8790
8791 /*
8792  * This subroutine is responsible for making sure that a particular
8793  * directory is connected to the root; if it isn't we trace it up as
8794  * far as we can go, and then offer to connect the resulting parent to
8795  * the lost+found.  We have to do loop detection; if we ever discover
8796  * a loop, we treat that as a disconnected directory and offer to
8797  * reparent it to lost+found.
8798  *
8799  * However, loop detection is expensive, because for very large
8800  * filesystems, the inode_loop_detect bitmap is huge, and clearing it
8801  * is non-trivial.  Loops in filesystems are also a rare error case,
8802  * and we shouldn't optimize for error cases.  So we try two passes of
8803  * the algorithm.  The first time, we ignore loop detection and merely
8804  * increment a counter; if the counter exceeds some extreme threshold,
8805  * then we try again with the loop detection bitmap enabled.
8806  */
8807 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
8808                            struct problem_context *pctx)
8809 {
8810         ext2_filsys     fs = ctx->fs;
8811         struct dir_info *p = dir;
8812         int             loop_pass = 0, parent_count = 0;
8813
8814         if (!p)
8815                 return 0;
8816
8817         while (1) {
8818                 /*
8819                  * Mark this inode as being "done"; by the time we
8820                  * return from this function, the inode we either be
8821                  * verified as being connected to the directory tree,
8822                  * or we will have offered to reconnect this to
8823                  * lost+found.
8824                  *
8825                  * If it was marked done already, then we've reached a
8826                  * parent we've already checked.
8827                  */
8828                 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
8829                         break;
8830
8831                 /*
8832                  * If this directory doesn't have a parent, or we've
8833                  * seen the parent once already, then offer to
8834                  * reparent it to lost+found
8835                  */
8836                 if (!p->parent ||
8837                     (loop_pass &&
8838                      (ext2fs_test_inode_bitmap(inode_loop_detect,
8839                                               p->parent)))) {
8840                         pctx->ino = p->ino;
8841                         if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
8842                                 if (e2fsck_reconnect_file(ctx, pctx->ino))
8843                                         ext2fs_unmark_valid(fs);
8844                                 else {
8845                                         p = e2fsck_get_dir_info(ctx, pctx->ino);
8846                                         p->parent = ctx->lost_and_found;
8847                                         fix_dotdot(ctx, p, ctx->lost_and_found);
8848                                 }
8849                         }
8850                         break;
8851                 }
8852                 p = e2fsck_get_dir_info(ctx, p->parent);
8853                 if (!p) {
8854                         fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
8855                         return 0;
8856                 }
8857                 if (loop_pass) {
8858                         ext2fs_mark_inode_bitmap(inode_loop_detect,
8859                                                  p->ino);
8860                 } else if (parent_count++ > 2048) {
8861                         /*
8862                          * If we've run into a path depth that's
8863                          * greater than 2048, try again with the inode
8864                          * loop bitmap turned on and start from the
8865                          * top.
8866                          */
8867                         loop_pass = 1;
8868                         if (inode_loop_detect)
8869                                 ext2fs_clear_inode_bitmap(inode_loop_detect);
8870                         else {
8871                                 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
8872                                 if (pctx->errcode) {
8873                                         pctx->num = 1;
8874                                         fix_problem(ctx,
8875                                     PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
8876                                         ctx->flags |= E2F_FLAG_ABORT;
8877                                         return -1;
8878                                 }
8879                         }
8880                         p = dir;
8881                 }
8882         }
8883
8884         /*
8885          * Make sure that .. and the parent directory are the same;
8886          * offer to fix it if not.
8887          */
8888         if (dir->parent != dir->dotdot) {
8889                 pctx->ino = dir->ino;
8890                 pctx->ino2 = dir->dotdot;
8891                 pctx->dir = dir->parent;
8892                 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
8893                         fix_dotdot(ctx, dir, dir->parent);
8894         }
8895         return 0;
8896 }
8897
8898 /*
8899  * This routine gets the lost_and_found inode, making it a directory
8900  * if necessary
8901  */
8902 ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
8903 {
8904         ext2_filsys fs = ctx->fs;
8905         ext2_ino_t                      ino;
8906         blk_t                   blk;
8907         errcode_t               retval;
8908         struct ext2_inode       inode;
8909         char *                  block;
8910         static const char       name[] = "lost+found";
8911         struct  problem_context pctx;
8912         struct dir_info         *dirinfo;
8913
8914         if (ctx->lost_and_found)
8915                 return ctx->lost_and_found;
8916
8917         clear_problem_context(&pctx);
8918
8919         retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
8920                                sizeof(name)-1, 0, &ino);
8921         if (retval && !fix)
8922                 return 0;
8923         if (!retval) {
8924                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
8925                         ctx->lost_and_found = ino;
8926                         return ino;
8927                 }
8928
8929                 /* Lost+found isn't a directory! */
8930                 if (!fix)
8931                         return 0;
8932                 pctx.ino = ino;
8933                 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
8934                         return 0;
8935
8936                 /* OK, unlink the old /lost+found file. */
8937                 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
8938                 if (pctx.errcode) {
8939                         pctx.str = "ext2fs_unlink";
8940                         fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
8941                         return 0;
8942                 }
8943                 dirinfo = e2fsck_get_dir_info(ctx, ino);
8944                 if (dirinfo)
8945                         dirinfo->parent = 0;
8946                 e2fsck_adjust_inode_count(ctx, ino, -1);
8947         } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
8948                 pctx.errcode = retval;
8949                 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
8950         }
8951         if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
8952                 return 0;
8953
8954         /*
8955          * Read the inode and block bitmaps in; we'll be messing with
8956          * them.
8957          */
8958         e2fsck_read_bitmaps(ctx);
8959
8960         /*
8961          * First, find a free block
8962          */
8963         retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8964         if (retval) {
8965                 pctx.errcode = retval;
8966                 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
8967                 return 0;
8968         }
8969         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8970         ext2fs_block_alloc_stats(fs, blk, +1);
8971
8972         /*
8973          * Next find a free inode.
8974          */
8975         retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
8976                                   ctx->inode_used_map, &ino);
8977         if (retval) {
8978                 pctx.errcode = retval;
8979                 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
8980                 return 0;
8981         }
8982         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
8983         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
8984         ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
8985
8986         /*
8987          * Now let's create the actual data block for the inode
8988          */
8989         retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
8990         if (retval) {
8991                 pctx.errcode = retval;
8992                 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
8993                 return 0;
8994         }
8995
8996         retval = ext2fs_write_dir_block(fs, blk, block);
8997         ext2fs_free_mem(&block);
8998         if (retval) {
8999                 pctx.errcode = retval;
9000                 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
9001                 return 0;
9002         }
9003
9004         /*
9005          * Set up the inode structure
9006          */
9007         memset(&inode, 0, sizeof(inode));
9008         inode.i_mode = 040700;
9009         inode.i_size = fs->blocksize;
9010         inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
9011         inode.i_links_count = 2;
9012         inode.i_blocks = fs->blocksize / 512;
9013         inode.i_block[0] = blk;
9014
9015         /*
9016          * Next, write out the inode.
9017          */
9018         pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
9019         if (pctx.errcode) {
9020                 pctx.str = "ext2fs_write_inode";
9021                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
9022                 return 0;
9023         }
9024         /*
9025          * Finally, create the directory link
9026          */
9027         pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
9028         if (pctx.errcode) {
9029                 pctx.str = "ext2fs_link";
9030                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
9031                 return 0;
9032         }
9033
9034         /*
9035          * Miscellaneous bookkeeping that needs to be kept straight.
9036          */
9037         e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
9038         e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
9039         ext2fs_icount_store(ctx->inode_count, ino, 2);
9040         ext2fs_icount_store(ctx->inode_link_info, ino, 2);
9041         ctx->lost_and_found = ino;
9042 #if 0
9043         printf("/lost+found created; inode #%lu\n", ino);
9044 #endif
9045         return ino;
9046 }
9047
9048 /*
9049  * This routine will connect a file to lost+found
9050  */
9051 int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
9052 {
9053         ext2_filsys fs = ctx->fs;
9054         errcode_t       retval;
9055         char            name[80];
9056         struct problem_context  pctx;
9057         struct ext2_inode       inode;
9058         int             file_type = 0;
9059
9060         clear_problem_context(&pctx);
9061         pctx.ino = ino;
9062
9063         if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
9064                 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
9065                         ctx->bad_lost_and_found++;
9066         }
9067         if (ctx->bad_lost_and_found) {
9068                 fix_problem(ctx, PR_3_NO_LPF, &pctx);
9069                 return 1;
9070         }
9071
9072         sprintf(name, "#%u", ino);
9073         if (ext2fs_read_inode(fs, ino, &inode) == 0)
9074                 file_type = ext2_file_type(inode.i_mode);
9075         retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
9076         if (retval == EXT2_ET_DIR_NO_SPACE) {
9077                 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
9078                         return 1;
9079                 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
9080                                                  1, 0);
9081                 if (retval) {
9082                         pctx.errcode = retval;
9083                         fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
9084                         return 1;
9085                 }
9086                 retval = ext2fs_link(fs, ctx->lost_and_found, name,
9087                                      ino, file_type);
9088         }
9089         if (retval) {
9090                 pctx.errcode = retval;
9091                 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
9092                 return 1;
9093         }
9094         e2fsck_adjust_inode_count(ctx, ino, 1);
9095
9096         return 0;
9097 }
9098
9099 /*
9100  * Utility routine to adjust the inode counts on an inode.
9101  */
9102 errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
9103 {
9104         ext2_filsys fs = ctx->fs;
9105         errcode_t               retval;
9106         struct ext2_inode       inode;
9107
9108         if (!ino)
9109                 return 0;
9110
9111         retval = ext2fs_read_inode(fs, ino, &inode);
9112         if (retval)
9113                 return retval;
9114
9115 #if 0
9116         printf("Adjusting link count for inode %lu by %d (from %d)\n", ino, adj,
9117                inode.i_links_count);
9118 #endif
9119
9120         if (adj == 1) {
9121                 ext2fs_icount_increment(ctx->inode_count, ino, 0);
9122                 if (inode.i_links_count == (__u16) ~0)
9123                         return 0;
9124                 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
9125                 inode.i_links_count++;
9126         } else if (adj == -1) {
9127                 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
9128                 if (inode.i_links_count == 0)
9129                         return 0;
9130                 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
9131                 inode.i_links_count--;
9132         }
9133
9134         retval = ext2fs_write_inode(fs, ino, &inode);
9135         if (retval)
9136                 return retval;
9137
9138         return 0;
9139 }
9140
9141 /*
9142  * Fix parent --- this routine fixes up the parent of a directory.
9143  */
9144 struct fix_dotdot_struct {
9145         ext2_filsys     fs;
9146         ext2_ino_t      parent;
9147         int             done;
9148         e2fsck_t        ctx;
9149 };
9150
9151 static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
9152                            int  offset FSCK_ATTR((unused)),
9153                            int  blocksize FSCK_ATTR((unused)),
9154                            char *buf FSCK_ATTR((unused)),
9155                            void *priv_data)
9156 {
9157         struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
9158         errcode_t       retval;
9159         struct problem_context pctx;
9160
9161         if ((dirent->name_len & 0xFF) != 2)
9162                 return 0;
9163         if (strncmp(dirent->name, "..", 2))
9164                 return 0;
9165
9166         clear_problem_context(&pctx);
9167
9168         retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
9169         if (retval) {
9170                 pctx.errcode = retval;
9171                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
9172         }
9173         retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
9174         if (retval) {
9175                 pctx.errcode = retval;
9176                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
9177         }
9178         dirent->inode = fp->parent;
9179
9180         fp->done++;
9181         return DIRENT_ABORT | DIRENT_CHANGED;
9182 }
9183
9184 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
9185 {
9186         ext2_filsys fs = ctx->fs;
9187         errcode_t       retval;
9188         struct fix_dotdot_struct fp;
9189         struct problem_context pctx;
9190
9191         fp.fs = fs;
9192         fp.parent = parent;
9193         fp.done = 0;
9194         fp.ctx = ctx;
9195
9196 #if 0
9197         printf("Fixing '..' of inode %lu to be %lu...\n", dir->ino, parent);
9198 #endif
9199
9200         retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
9201                                     0, fix_dotdot_proc, &fp);
9202         if (retval || !fp.done) {
9203                 clear_problem_context(&pctx);
9204                 pctx.ino = dir->ino;
9205                 pctx.errcode = retval;
9206                 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
9207                             PR_3_FIX_PARENT_NOFIND, &pctx);
9208                 ext2fs_unmark_valid(fs);
9209         }
9210         dir->dotdot = parent;
9211
9212         return;
9213 }
9214
9215 /*
9216  * These routines are responsible for expanding a /lost+found if it is
9217  * too small.
9218  */
9219
9220 struct expand_dir_struct {
9221         int                     num;
9222         int                     guaranteed_size;
9223         int                     newblocks;
9224         int                     last_block;
9225         errcode_t               err;
9226         e2fsck_t                ctx;
9227 };
9228
9229 static int expand_dir_proc(ext2_filsys fs,
9230                            blk_t        *blocknr,
9231                            e2_blkcnt_t  blockcnt,
9232                            blk_t ref_block FSCK_ATTR((unused)),
9233                            int ref_offset FSCK_ATTR((unused)),
9234                            void *priv_data)
9235 {
9236         struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
9237         blk_t   new_blk;
9238         static blk_t    last_blk = 0;
9239         char            *block;
9240         errcode_t       retval;
9241         e2fsck_t        ctx;
9242
9243         ctx = es->ctx;
9244
9245         if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
9246                 return BLOCK_ABORT;
9247
9248         if (blockcnt > 0)
9249                 es->last_block = blockcnt;
9250         if (*blocknr) {
9251                 last_blk = *blocknr;
9252                 return 0;
9253         }
9254         retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
9255                                   &new_blk);
9256         if (retval) {
9257                 es->err = retval;
9258                 return BLOCK_ABORT;
9259         }
9260         if (blockcnt > 0) {
9261                 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
9262                 if (retval) {
9263                         es->err = retval;
9264                         return BLOCK_ABORT;
9265                 }
9266                 es->num--;
9267                 retval = ext2fs_write_dir_block(fs, new_blk, block);
9268         } else {
9269                 retval = ext2fs_get_mem(fs->blocksize, &block);
9270                 if (retval) {
9271                         es->err = retval;
9272                         return BLOCK_ABORT;
9273                 }
9274                 memset(block, 0, fs->blocksize);
9275                 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
9276         }
9277         if (retval) {
9278                 es->err = retval;
9279                 return BLOCK_ABORT;
9280         }
9281         ext2fs_free_mem(&block);
9282         *blocknr = new_blk;
9283         ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
9284         ext2fs_block_alloc_stats(fs, new_blk, +1);
9285         es->newblocks++;
9286
9287         if (es->num == 0)
9288                 return (BLOCK_CHANGED | BLOCK_ABORT);
9289         else
9290                 return BLOCK_CHANGED;
9291 }
9292
9293 errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
9294                                   int num, int guaranteed_size)
9295 {
9296         ext2_filsys fs = ctx->fs;
9297         errcode_t       retval;
9298         struct expand_dir_struct es;
9299         struct ext2_inode       inode;
9300
9301         if (!(fs->flags & EXT2_FLAG_RW))
9302                 return EXT2_ET_RO_FILSYS;
9303
9304         /*
9305          * Read the inode and block bitmaps in; we'll be messing with
9306          * them.
9307          */
9308         e2fsck_read_bitmaps(ctx);
9309
9310         retval = ext2fs_check_directory(fs, dir);
9311         if (retval)
9312                 return retval;
9313
9314         es.num = num;
9315         es.guaranteed_size = guaranteed_size;
9316         es.last_block = 0;
9317         es.err = 0;
9318         es.newblocks = 0;
9319         es.ctx = ctx;
9320
9321         retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
9322                                        0, expand_dir_proc, &es);
9323
9324         if (es.err)
9325                 return es.err;
9326
9327         /*
9328          * Update the size and block count fields in the inode.
9329          */
9330         retval = ext2fs_read_inode(fs, dir, &inode);
9331         if (retval)
9332                 return retval;
9333
9334         inode.i_size = (es.last_block + 1) * fs->blocksize;
9335         inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
9336
9337         e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
9338
9339         return 0;
9340 }
9341
9342 /*
9343  * pass4.c -- pass #4 of e2fsck: Check reference counts
9344  *
9345  * Pass 4 frees the following data structures:
9346  *      - A bitmap of which inodes are in bad blocks.   (inode_bb_map)
9347  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
9348  */
9349
9350 /*
9351  * This routine is called when an inode is not connected to the
9352  * directory tree.
9353  *
9354  * This subroutine returns 1 then the caller shouldn't bother with the
9355  * rest of the pass 4 tests.
9356  */
9357 static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
9358 {
9359         ext2_filsys fs = ctx->fs;
9360         struct ext2_inode       inode;
9361         struct problem_context  pctx;
9362
9363         e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
9364         clear_problem_context(&pctx);
9365         pctx.ino = i;
9366         pctx.inode = &inode;
9367
9368         /*
9369          * Offer to delete any zero-length files that does not have
9370          * blocks.  If there is an EA block, it might have useful
9371          * information, so we won't prompt to delete it, but let it be
9372          * reconnected to lost+found.
9373          */
9374         if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
9375                                 LINUX_S_ISDIR(inode.i_mode))) {
9376                 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
9377                         ext2fs_icount_store(ctx->inode_link_info, i, 0);
9378                         inode.i_links_count = 0;
9379                         inode.i_dtime = time(0);
9380                         e2fsck_write_inode(ctx, i, &inode,
9381                                            "disconnect_inode");
9382                         /*
9383                          * Fix up the bitmaps...
9384                          */
9385                         e2fsck_read_bitmaps(ctx);
9386                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
9387                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
9388                         ext2fs_inode_alloc_stats2(fs, i, -1,
9389                                                   LINUX_S_ISDIR(inode.i_mode));
9390                         return 0;
9391                 }
9392         }
9393
9394         /*
9395          * Prompt to reconnect.
9396          */
9397         if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
9398                 if (e2fsck_reconnect_file(ctx, i))
9399                         ext2fs_unmark_valid(fs);
9400         } else {
9401                 /*
9402                  * If we don't attach the inode, then skip the
9403                  * i_links_test since there's no point in trying to
9404                  * force i_links_count to zero.
9405                  */
9406                 ext2fs_unmark_valid(fs);
9407                 return 1;
9408         }
9409         return 0;
9410 }
9411
9412
9413 static void e2fsck_pass4(e2fsck_t ctx)
9414 {
9415         ext2_filsys fs = ctx->fs;
9416         ext2_ino_t      i;
9417         struct ext2_inode       inode;
9418 #ifdef RESOURCE_TRACK
9419         struct resource_track   rtrack;
9420 #endif
9421         struct problem_context  pctx;
9422         __u16   link_count, link_counted;
9423         char    *buf = 0;
9424         int     group, maxgroup;
9425
9426 #ifdef RESOURCE_TRACK
9427         init_resource_track(&rtrack);
9428 #endif
9429
9430 #ifdef MTRACE
9431         mtrace_print("Pass 4");
9432 #endif
9433
9434         clear_problem_context(&pctx);
9435
9436         if (!(ctx->options & E2F_OPT_PREEN))
9437                 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
9438
9439         group = 0;
9440         maxgroup = fs->group_desc_count;
9441         if (ctx->progress)
9442                 if ((ctx->progress)(ctx, 4, 0, maxgroup))
9443                         return;
9444
9445         for (i=1; i <= fs->super->s_inodes_count; i++) {
9446                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9447                         return;
9448                 if ((i % fs->super->s_inodes_per_group) == 0) {
9449                         group++;
9450                         if (ctx->progress)
9451                                 if ((ctx->progress)(ctx, 4, group, maxgroup))
9452                                         return;
9453                 }
9454                 if (i == EXT2_BAD_INO ||
9455                     (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
9456                         continue;
9457                 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
9458                     (ctx->inode_imagic_map &&
9459                      ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)) ||
9460                     (ctx->inode_bb_map &&
9461                      ext2fs_test_inode_bitmap(ctx->inode_bb_map, i)))
9462                         continue;
9463                 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
9464                 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
9465                 if (link_counted == 0) {
9466                         if (!buf)
9467                                 buf = e2fsck_allocate_memory(ctx,
9468                                      fs->blocksize, "bad_inode buffer");
9469                         if (e2fsck_process_bad_inode(ctx, 0, i, buf))
9470                                 continue;
9471                         if (disconnect_inode(ctx, i))
9472                                 continue;
9473                         ext2fs_icount_fetch(ctx->inode_link_info, i,
9474                                             &link_count);
9475                         ext2fs_icount_fetch(ctx->inode_count, i,
9476                                             &link_counted);
9477                 }
9478                 if (link_counted != link_count) {
9479                         e2fsck_read_inode(ctx, i, &inode, "pass4");
9480                         pctx.ino = i;
9481                         pctx.inode = &inode;
9482                         if (link_count != inode.i_links_count) {
9483                                 pctx.num = link_count;
9484                                 fix_problem(ctx,
9485                                             PR_4_INCONSISTENT_COUNT, &pctx);
9486                         }
9487                         pctx.num = link_counted;
9488                         if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
9489                                 inode.i_links_count = link_counted;
9490                                 e2fsck_write_inode(ctx, i, &inode, "pass4");
9491                         }
9492                 }
9493         }
9494         ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
9495         ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
9496         ext2fs_free_inode_bitmap(ctx->inode_bb_map);
9497         ctx->inode_bb_map = 0;
9498         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
9499         ctx->inode_imagic_map = 0;
9500         if (buf)
9501                 ext2fs_free_mem(&buf);
9502 #ifdef RESOURCE_TRACK
9503         if (ctx->options & E2F_OPT_TIME2) {
9504                 e2fsck_clear_progbar(ctx);
9505                 print_resource_track(_("Pass 4"), &rtrack);
9506         }
9507 #endif
9508 }
9509
9510 /*
9511  * pass5.c --- check block and inode bitmaps against on-disk bitmaps
9512  */
9513
9514 #define NO_BLK ((blk_t) -1)
9515
9516 static void print_bitmap_problem(e2fsck_t ctx, int problem,
9517                             struct problem_context *pctx)
9518 {
9519         switch (problem) {
9520         case PR_5_BLOCK_UNUSED:
9521                 if (pctx->blk == pctx->blk2)
9522                         pctx->blk2 = 0;
9523                 else
9524                         problem = PR_5_BLOCK_RANGE_UNUSED;
9525                 break;
9526         case PR_5_BLOCK_USED:
9527                 if (pctx->blk == pctx->blk2)
9528                         pctx->blk2 = 0;
9529                 else
9530                         problem = PR_5_BLOCK_RANGE_USED;
9531                 break;
9532         case PR_5_INODE_UNUSED:
9533                 if (pctx->ino == pctx->ino2)
9534                         pctx->ino2 = 0;
9535                 else
9536                         problem = PR_5_INODE_RANGE_UNUSED;
9537                 break;
9538         case PR_5_INODE_USED:
9539                 if (pctx->ino == pctx->ino2)
9540                         pctx->ino2 = 0;
9541                 else
9542                         problem = PR_5_INODE_RANGE_USED;
9543                 break;
9544         }
9545         fix_problem(ctx, problem, pctx);
9546         pctx->blk = pctx->blk2 = NO_BLK;
9547         pctx->ino = pctx->ino2 = 0;
9548 }
9549
9550 static void check_block_bitmaps(e2fsck_t ctx)
9551 {
9552         ext2_filsys fs = ctx->fs;
9553         blk_t   i;
9554         int     *free_array;
9555         int     group = 0;
9556         unsigned int    blocks = 0;
9557         unsigned int    free_blocks = 0;
9558         int     group_free = 0;
9559         int     actual, bitmap;
9560         struct problem_context  pctx;
9561         int     problem, save_problem, fixit, had_problem;
9562         errcode_t       retval;
9563
9564         clear_problem_context(&pctx);
9565         free_array = (int *) e2fsck_allocate_memory(ctx,
9566             fs->group_desc_count * sizeof(int), "free block count array");
9567
9568         if ((fs->super->s_first_data_block <
9569              ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
9570             (fs->super->s_blocks_count-1 >
9571              ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
9572                 pctx.num = 1;
9573                 pctx.blk = fs->super->s_first_data_block;
9574                 pctx.blk2 = fs->super->s_blocks_count -1;
9575                 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
9576                 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
9577                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9578
9579                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9580                 return;
9581         }
9582
9583         if ((fs->super->s_first_data_block <
9584              ext2fs_get_block_bitmap_start(fs->block_map)) ||
9585             (fs->super->s_blocks_count-1 >
9586              ext2fs_get_block_bitmap_end(fs->block_map))) {
9587                 pctx.num = 2;
9588                 pctx.blk = fs->super->s_first_data_block;
9589                 pctx.blk2 = fs->super->s_blocks_count -1;
9590                 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
9591                 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
9592                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9593
9594                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9595                 return;
9596         }
9597
9598 redo_counts:
9599         had_problem = 0;
9600         save_problem = 0;
9601         pctx.blk = pctx.blk2 = NO_BLK;
9602         for (i = fs->super->s_first_data_block;
9603              i < fs->super->s_blocks_count;
9604              i++) {
9605                 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
9606                 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
9607
9608                 if (actual == bitmap)
9609                         goto do_counts;
9610
9611                 if (!actual && bitmap) {
9612                         /*
9613                          * Block not used, but marked in use in the bitmap.
9614                          */
9615                         problem = PR_5_BLOCK_UNUSED;
9616                 } else {
9617                         /*
9618                          * Block used, but not marked in use in the bitmap.
9619                          */
9620                         problem = PR_5_BLOCK_USED;
9621                 }
9622                 if (pctx.blk == NO_BLK) {
9623                         pctx.blk = pctx.blk2 = i;
9624                         save_problem = problem;
9625                 } else {
9626                         if ((problem == save_problem) &&
9627                             (pctx.blk2 == i-1))
9628                                 pctx.blk2++;
9629                         else {
9630                                 print_bitmap_problem(ctx, save_problem, &pctx);
9631                                 pctx.blk = pctx.blk2 = i;
9632                                 save_problem = problem;
9633                         }
9634                 }
9635                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
9636                 had_problem++;
9637
9638         do_counts:
9639                 if (!bitmap) {
9640                         group_free++;
9641                         free_blocks++;
9642                 }
9643                 blocks ++;
9644                 if ((blocks == fs->super->s_blocks_per_group) ||
9645                     (i == fs->super->s_blocks_count-1)) {
9646                         free_array[group] = group_free;
9647                         group ++;
9648                         blocks = 0;
9649                         group_free = 0;
9650                         if (ctx->progress)
9651                                 if ((ctx->progress)(ctx, 5, group,
9652                                                     fs->group_desc_count*2))
9653                                         return;
9654                 }
9655         }
9656         if (pctx.blk != NO_BLK)
9657                 print_bitmap_problem(ctx, save_problem, &pctx);
9658         if (had_problem)
9659                 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
9660         else
9661                 fixit = -1;
9662         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
9663
9664         if (fixit == 1) {
9665                 ext2fs_free_block_bitmap(fs->block_map);
9666                 retval = ext2fs_copy_bitmap(ctx->block_found_map,
9667                                                   &fs->block_map);
9668                 if (retval) {
9669                         clear_problem_context(&pctx);
9670                         fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
9671                         ctx->flags |= E2F_FLAG_ABORT;
9672                         return;
9673                 }
9674                 ext2fs_set_bitmap_padding(fs->block_map);
9675                 ext2fs_mark_bb_dirty(fs);
9676
9677                 /* Redo the counts */
9678                 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
9679                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
9680                 goto redo_counts;
9681         } else if (fixit == 0)
9682                 ext2fs_unmark_valid(fs);
9683
9684         for (i = 0; i < fs->group_desc_count; i++) {
9685                 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
9686                         pctx.group = i;
9687                         pctx.blk = fs->group_desc[i].bg_free_blocks_count;
9688                         pctx.blk2 = free_array[i];
9689
9690                         if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
9691                                         &pctx)) {
9692                                 fs->group_desc[i].bg_free_blocks_count =
9693                                         free_array[i];
9694                                 ext2fs_mark_super_dirty(fs);
9695                         } else
9696                                 ext2fs_unmark_valid(fs);
9697                 }
9698         }
9699         if (free_blocks != fs->super->s_free_blocks_count) {
9700                 pctx.group = 0;
9701                 pctx.blk = fs->super->s_free_blocks_count;
9702                 pctx.blk2 = free_blocks;
9703
9704                 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
9705                         fs->super->s_free_blocks_count = free_blocks;
9706                         ext2fs_mark_super_dirty(fs);
9707                 } else
9708                         ext2fs_unmark_valid(fs);
9709         }
9710         ext2fs_free_mem(&free_array);
9711 }
9712
9713 static void check_inode_bitmaps(e2fsck_t ctx)
9714 {
9715         ext2_filsys fs = ctx->fs;
9716         ext2_ino_t      i;
9717         unsigned int    free_inodes = 0;
9718         int             group_free = 0;
9719         int             dirs_count = 0;
9720         int             group = 0;
9721         unsigned int    inodes = 0;
9722         int             *free_array;
9723         int             *dir_array;
9724         int             actual, bitmap;
9725         errcode_t       retval;
9726         struct problem_context  pctx;
9727         int             problem, save_problem, fixit, had_problem;
9728
9729         clear_problem_context(&pctx);
9730         free_array = (int *) e2fsck_allocate_memory(ctx,
9731             fs->group_desc_count * sizeof(int), "free inode count array");
9732
9733         dir_array = (int *) e2fsck_allocate_memory(ctx,
9734            fs->group_desc_count * sizeof(int), "directory count array");
9735
9736         if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
9737             (fs->super->s_inodes_count >
9738              ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
9739                 pctx.num = 3;
9740                 pctx.blk = 1;
9741                 pctx.blk2 = fs->super->s_inodes_count;
9742                 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
9743                 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
9744                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9745
9746                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9747                 return;
9748         }
9749         if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
9750             (fs->super->s_inodes_count >
9751              ext2fs_get_inode_bitmap_end(fs->inode_map))) {
9752                 pctx.num = 4;
9753                 pctx.blk = 1;
9754                 pctx.blk2 = fs->super->s_inodes_count;
9755                 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
9756                 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
9757                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9758
9759                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9760                 return;
9761         }
9762
9763 redo_counts:
9764         had_problem = 0;
9765         save_problem = 0;
9766         pctx.ino = pctx.ino2 = 0;
9767         for (i = 1; i <= fs->super->s_inodes_count; i++) {
9768                 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
9769                 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
9770
9771                 if (actual == bitmap)
9772                         goto do_counts;
9773
9774                 if (!actual && bitmap) {
9775                         /*
9776                          * Inode wasn't used, but marked in bitmap
9777                          */
9778                         problem = PR_5_INODE_UNUSED;
9779                 } else /* if (actual && !bitmap) */ {
9780                         /*
9781                          * Inode used, but not in bitmap
9782                          */
9783                         problem = PR_5_INODE_USED;
9784                 }
9785                 if (pctx.ino == 0) {
9786                         pctx.ino = pctx.ino2 = i;
9787                         save_problem = problem;
9788                 } else {
9789                         if ((problem == save_problem) &&
9790                             (pctx.ino2 == i-1))
9791                                 pctx.ino2++;
9792                         else {
9793                                 print_bitmap_problem(ctx, save_problem, &pctx);
9794                                 pctx.ino = pctx.ino2 = i;
9795                                 save_problem = problem;
9796                         }
9797                 }
9798                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
9799                 had_problem++;
9800
9801 do_counts:
9802                 if (!bitmap) {
9803                         group_free++;
9804                         free_inodes++;
9805                 } else {
9806                         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
9807                                 dirs_count++;
9808                 }
9809                 inodes++;
9810                 if ((inodes == fs->super->s_inodes_per_group) ||
9811                     (i == fs->super->s_inodes_count)) {
9812                         free_array[group] = group_free;
9813                         dir_array[group] = dirs_count;
9814                         group ++;
9815                         inodes = 0;
9816                         group_free = 0;
9817                         dirs_count = 0;
9818                         if (ctx->progress)
9819                                 if ((ctx->progress)(ctx, 5,
9820                                             group + fs->group_desc_count,
9821                                             fs->group_desc_count*2))
9822                                         return;
9823                 }
9824         }
9825         if (pctx.ino)
9826                 print_bitmap_problem(ctx, save_problem, &pctx);
9827
9828         if (had_problem)
9829                 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
9830         else
9831                 fixit = -1;
9832         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
9833
9834         if (fixit == 1) {
9835                 ext2fs_free_inode_bitmap(fs->inode_map);
9836                 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
9837                                                   &fs->inode_map);
9838                 if (retval) {
9839                         clear_problem_context(&pctx);
9840                         fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
9841                         ctx->flags |= E2F_FLAG_ABORT;
9842                         return;
9843                 }
9844                 ext2fs_set_bitmap_padding(fs->inode_map);
9845                 ext2fs_mark_ib_dirty(fs);
9846
9847                 /* redo counts */
9848                 inodes = 0; free_inodes = 0; group_free = 0;
9849                 dirs_count = 0; group = 0;
9850                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
9851                 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
9852                 goto redo_counts;
9853         } else if (fixit == 0)
9854                 ext2fs_unmark_valid(fs);
9855
9856         for (i = 0; i < fs->group_desc_count; i++) {
9857                 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
9858                         pctx.group = i;
9859                         pctx.ino = fs->group_desc[i].bg_free_inodes_count;
9860                         pctx.ino2 = free_array[i];
9861                         if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
9862                                         &pctx)) {
9863                                 fs->group_desc[i].bg_free_inodes_count =
9864                                         free_array[i];
9865                                 ext2fs_mark_super_dirty(fs);
9866                         } else
9867                                 ext2fs_unmark_valid(fs);
9868                 }
9869                 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
9870                         pctx.group = i;
9871                         pctx.ino = fs->group_desc[i].bg_used_dirs_count;
9872                         pctx.ino2 = dir_array[i];
9873
9874                         if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
9875                                         &pctx)) {
9876                                 fs->group_desc[i].bg_used_dirs_count =
9877                                         dir_array[i];
9878                                 ext2fs_mark_super_dirty(fs);
9879                         } else
9880                                 ext2fs_unmark_valid(fs);
9881                 }
9882         }
9883         if (free_inodes != fs->super->s_free_inodes_count) {
9884                 pctx.group = -1;
9885                 pctx.ino = fs->super->s_free_inodes_count;
9886                 pctx.ino2 = free_inodes;
9887
9888                 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
9889                         fs->super->s_free_inodes_count = free_inodes;
9890                         ext2fs_mark_super_dirty(fs);
9891                 } else
9892                         ext2fs_unmark_valid(fs);
9893         }
9894         ext2fs_free_mem(&free_array);
9895         ext2fs_free_mem(&dir_array);
9896 }
9897
9898 static void check_inode_end(e2fsck_t ctx)
9899 {
9900         ext2_filsys fs = ctx->fs;
9901         ext2_ino_t      end, save_inodes_count, i;
9902         struct problem_context  pctx;
9903
9904         clear_problem_context(&pctx);
9905
9906         end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
9907         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
9908                                                      &save_inodes_count);
9909         if (pctx.errcode) {
9910                 pctx.num = 1;
9911                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9912                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9913                 return;
9914         }
9915         if (save_inodes_count == end)
9916                 return;
9917
9918         for (i = save_inodes_count + 1; i <= end; i++) {
9919                 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
9920                         if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
9921                                 for (i = save_inodes_count + 1; i <= end; i++)
9922                                         ext2fs_mark_inode_bitmap(fs->inode_map,
9923                                                                  i);
9924                                 ext2fs_mark_ib_dirty(fs);
9925                         } else
9926                                 ext2fs_unmark_valid(fs);
9927                         break;
9928                 }
9929         }
9930
9931         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
9932                                                      save_inodes_count, 0);
9933         if (pctx.errcode) {
9934                 pctx.num = 2;
9935                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9936                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9937                 return;
9938         }
9939 }
9940
9941 static void check_block_end(e2fsck_t ctx)
9942 {
9943         ext2_filsys fs = ctx->fs;
9944         blk_t   end, save_blocks_count, i;
9945         struct problem_context  pctx;
9946
9947         clear_problem_context(&pctx);
9948
9949         end = fs->block_map->start +
9950                 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
9951         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
9952                                                      &save_blocks_count);
9953         if (pctx.errcode) {
9954                 pctx.num = 3;
9955                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9956                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9957                 return;
9958         }
9959         if (save_blocks_count == end)
9960                 return;
9961
9962         for (i = save_blocks_count + 1; i <= end; i++) {
9963                 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
9964                         if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
9965                                 for (i = save_blocks_count + 1; i <= end; i++)
9966                                         ext2fs_mark_block_bitmap(fs->block_map,
9967                                                                  i);
9968                                 ext2fs_mark_bb_dirty(fs);
9969                         } else
9970                                 ext2fs_unmark_valid(fs);
9971                         break;
9972                 }
9973         }
9974
9975         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
9976                                                      save_blocks_count, 0);
9977         if (pctx.errcode) {
9978                 pctx.num = 4;
9979                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9980                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9981                 return;
9982         }
9983 }
9984
9985 static void e2fsck_pass5(e2fsck_t ctx)
9986 {
9987 #ifdef RESOURCE_TRACK
9988         struct resource_track   rtrack;
9989 #endif
9990         struct problem_context  pctx;
9991
9992 #ifdef MTRACE
9993         mtrace_print("Pass 5");
9994 #endif
9995
9996 #ifdef RESOURCE_TRACK
9997         init_resource_track(&rtrack);
9998 #endif
9999
10000         clear_problem_context(&pctx);
10001
10002         if (!(ctx->options & E2F_OPT_PREEN))
10003                 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
10004
10005         if (ctx->progress)
10006                 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
10007                         return;
10008
10009         e2fsck_read_bitmaps(ctx);
10010
10011         check_block_bitmaps(ctx);
10012         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
10013                 return;
10014         check_inode_bitmaps(ctx);
10015         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
10016                 return;
10017         check_inode_end(ctx);
10018         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
10019                 return;
10020         check_block_end(ctx);
10021         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
10022                 return;
10023
10024         ext2fs_free_inode_bitmap(ctx->inode_used_map);
10025         ctx->inode_used_map = 0;
10026         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
10027         ctx->inode_dir_map = 0;
10028         ext2fs_free_block_bitmap(ctx->block_found_map);
10029         ctx->block_found_map = 0;
10030
10031 #ifdef RESOURCE_TRACK
10032         if (ctx->options & E2F_OPT_TIME2) {
10033                 e2fsck_clear_progbar(ctx);
10034                 print_resource_track(_("Pass 5"), &rtrack);
10035         }
10036 #endif
10037 }
10038
10039 /*
10040  * problem.c --- report filesystem problems to the user
10041  */
10042
10043 #define PR_PREEN_OK     0x000001 /* Don't need to do preenhalt */
10044 #define PR_NO_OK        0x000002 /* If user answers no, don't make fs invalid */
10045 #define PR_NO_DEFAULT   0x000004 /* Default to no */
10046 #define PR_MSG_ONLY     0x000008 /* Print message only */
10047
10048 /* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
10049
10050 #define PR_FATAL        0x001000 /* Fatal error */
10051 #define PR_AFTER_CODE   0x002000 /* After asking the first question, */
10052                                  /* ask another */
10053 #define PR_PREEN_NOMSG  0x004000 /* Don't print a message if we're preening */
10054 #define PR_NOCOLLATE    0x008000 /* Don't collate answers for this latch */
10055 #define PR_NO_NOMSG     0x010000 /* Don't print a message if e2fsck -n */
10056 #define PR_PREEN_NO     0x020000 /* Use No as an answer if preening */
10057 #define PR_PREEN_NOHDR  0x040000 /* Don't print the preen header */
10058
10059
10060 #define PROMPT_NONE     0
10061 #define PROMPT_FIX      1
10062 #define PROMPT_CLEAR    2
10063 #define PROMPT_RELOCATE 3
10064 #define PROMPT_ALLOCATE 4
10065 #define PROMPT_EXPAND   5
10066 #define PROMPT_CONNECT  6
10067 #define PROMPT_CREATE   7
10068 #define PROMPT_SALVAGE  8
10069 #define PROMPT_TRUNCATE 9
10070 #define PROMPT_CLEAR_INODE 10
10071 #define PROMPT_ABORT    11
10072 #define PROMPT_SPLIT    12
10073 #define PROMPT_CONTINUE 13
10074 #define PROMPT_CLONE    14
10075 #define PROMPT_DELETE   15
10076 #define PROMPT_SUPPRESS 16
10077 #define PROMPT_UNLINK   17
10078 #define PROMPT_CLEAR_HTREE 18
10079 #define PROMPT_RECREATE 19
10080 #define PROMPT_NULL     20
10081
10082 struct e2fsck_problem {
10083         problem_t       e2p_code;
10084         const char *    e2p_description;
10085         char            prompt;
10086         int             flags;
10087         problem_t       second_code;
10088 };
10089
10090 struct latch_descr {
10091         int             latch_code;
10092         problem_t       question;
10093         problem_t       end_message;
10094         int             flags;
10095 };
10096
10097 /*
10098  * These are the prompts which are used to ask the user if they want
10099  * to fix a problem.
10100  */
10101 static const char * const prompt[] = {
10102         N_("(no prompt)"),      /* 0 */
10103         N_("Fix"),              /* 1 */
10104         N_("Clear"),            /* 2 */
10105         N_("Relocate"),         /* 3 */
10106         N_("Allocate"),         /* 4 */
10107         N_("Expand"),           /* 5 */
10108         N_("Connect to /lost+found"), /* 6 */
10109         N_("Create"),           /* 7 */
10110         N_("Salvage"),          /* 8 */
10111         N_("Truncate"),         /* 9 */
10112         N_("Clear inode"),      /* 10 */
10113         N_("Abort"),            /* 11 */
10114         N_("Split"),            /* 12 */
10115         N_("Continue"),         /* 13 */
10116         N_("Clone duplicate/bad blocks"), /* 14 */
10117         N_("Delete file"),      /* 15 */
10118         N_("Suppress messages"),/* 16 */
10119         N_("Unlink"),           /* 17 */
10120         N_("Clear HTree index"),/* 18 */
10121         N_("Recreate"),         /* 19 */
10122         "",                     /* 20 */
10123 };
10124
10125 /*
10126  * These messages are printed when we are preen mode and we will be
10127  * automatically fixing the problem.
10128  */
10129 static const char * const preen_msg[] = {
10130         N_("(NONE)"),           /* 0 */
10131         N_("FIXED"),            /* 1 */
10132         N_("CLEARED"),          /* 2 */
10133         N_("RELOCATED"),        /* 3 */
10134         N_("ALLOCATED"),        /* 4 */
10135         N_("EXPANDED"),         /* 5 */
10136         N_("RECONNECTED"),      /* 6 */
10137         N_("CREATED"),          /* 7 */
10138         N_("SALVAGED"),         /* 8 */
10139         N_("TRUNCATED"),        /* 9 */
10140         N_("INODE CLEARED"),    /* 10 */
10141         N_("ABORTED"),          /* 11 */
10142         N_("SPLIT"),            /* 12 */
10143         N_("CONTINUING"),       /* 13 */
10144         N_("DUPLICATE/BAD BLOCKS CLONED"), /* 14 */
10145         N_("FILE DELETED"),     /* 15 */
10146         N_("SUPPRESSED"),       /* 16 */
10147         N_("UNLINKED"),         /* 17 */
10148         N_("HTREE INDEX CLEARED"),/* 18 */
10149         N_("WILL RECREATE"),    /* 19 */
10150         "",                     /* 20 */
10151 };
10152
10153 static const struct e2fsck_problem problem_table[] = {
10154
10155         /* Pre-Pass 1 errors */
10156
10157         /* Block bitmap not in group */
10158         { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g.  (@b %b)\n"),
10159           PROMPT_RELOCATE, PR_LATCH_RELOC },
10160
10161         /* Inode bitmap not in group */
10162         { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g.  (@b %b)\n"),
10163           PROMPT_RELOCATE, PR_LATCH_RELOC },
10164
10165         /* Inode table not in group */
10166         { PR_0_ITABLE_NOT_GROUP,
10167           N_("@i table for @g %g is not in @g.  (@b %b)\n"
10168           "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
10169           PROMPT_RELOCATE, PR_LATCH_RELOC },
10170
10171         /* Superblock corrupt */
10172         { PR_0_SB_CORRUPT,
10173           N_("\nThe @S could not be read or does not describe a correct ext2\n"
10174           "@f.  If the @v is valid and it really contains an ext2\n"
10175           "@f (and not swap or ufs or something else), then the @S\n"
10176           "is corrupt, and you might try running e2fsck with an alternate @S:\n"
10177           "    e2fsck -b %S <@v>\n\n"),
10178           PROMPT_NONE, PR_FATAL },
10179
10180         /* Filesystem size is wrong */
10181         { PR_0_FS_SIZE_WRONG,
10182           N_("The @f size (according to the @S) is %b @bs\n"
10183           "The physical size of the @v is %c @bs\n"
10184           "Either the @S or the partition table is likely to be corrupt!\n"),
10185           PROMPT_ABORT, 0 },
10186
10187         /* Fragments not supported */
10188         { PR_0_NO_FRAGMENTS,
10189           N_("@S @b_size = %b, fragsize = %c.\n"
10190           "This version of e2fsck does not support fragment sizes different\n"
10191           "from the @b size.\n"),
10192           PROMPT_NONE, PR_FATAL },
10193
10194           /* Bad blocks_per_group */
10195         { PR_0_BLOCKS_PER_GROUP,
10196           N_("@S @bs_per_group = %b, should have been %c\n"),
10197           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
10198
10199         /* Bad first_data_block */
10200         { PR_0_FIRST_DATA_BLOCK,
10201           N_("@S first_data_@b = %b, should have been %c\n"),
10202           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
10203
10204         /* Adding UUID to filesystem */
10205         { PR_0_ADD_UUID,
10206           N_("@f did not have a UUID; generating one.\n\n"),
10207           PROMPT_NONE, 0 },
10208
10209         /* Relocate hint */
10210         { PR_0_RELOCATE_HINT,
10211           N_("Note: if there is several inode or block bitmap blocks\n"
10212           "which require relocation, or one part of the inode table\n"
10213           "which must be moved, you may wish to try running e2fsck\n"
10214           "with the '-b %S' option first.  The problem may lie only\n"
10215           "with the primary block group descriptor, and the backup\n"
10216           "block group descriptor may be OK.\n\n"),
10217           PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
10218
10219         /* Miscellaneous superblock corruption */
10220         { PR_0_MISC_CORRUPT_SUPER,
10221           N_("Corruption found in @S.  (%s = %N).\n"),
10222           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
10223
10224         /* Error determing physical device size of filesystem */
10225         { PR_0_GETSIZE_ERROR,
10226           N_("Error determining size of the physical @v: %m\n"),
10227           PROMPT_NONE, PR_FATAL },
10228
10229         /* Inode count in superblock is incorrect */
10230         { PR_0_INODE_COUNT_WRONG,
10231           N_("@i count in @S is %i, should be %j.\n"),
10232           PROMPT_FIX, 0 },
10233
10234         { PR_0_HURD_CLEAR_FILETYPE,
10235           N_("The Hurd does not support the filetype feature.\n"),
10236           PROMPT_CLEAR, 0 },
10237
10238         /* Journal inode is invalid */
10239         { PR_0_JOURNAL_BAD_INODE,
10240           N_("@S has a bad ext3 @j (@i %i).\n"),
10241           PROMPT_CLEAR, PR_PREEN_OK },
10242
10243         /* The external journal has (unsupported) multiple filesystems */
10244         { PR_0_JOURNAL_UNSUPP_MULTIFS,
10245           N_("External @j has multiple @f users (unsupported).\n"),
10246           PROMPT_NONE, PR_FATAL },
10247
10248         /* Can't find external journal */
10249         { PR_0_CANT_FIND_JOURNAL,
10250           N_("Can't find external @j\n"),
10251           PROMPT_NONE, PR_FATAL },
10252
10253         /* External journal has bad superblock */
10254         { PR_0_EXT_JOURNAL_BAD_SUPER,
10255           N_("External @j has bad @S\n"),
10256           PROMPT_NONE, PR_FATAL },
10257
10258         /* Superblock has a bad journal UUID */
10259         { PR_0_JOURNAL_BAD_UUID,
10260           N_("External @j does not support this @f\n"),
10261           PROMPT_NONE, PR_FATAL },
10262
10263         /* Journal has an unknown superblock type */
10264         { PR_0_JOURNAL_UNSUPP_SUPER,
10265           N_("Ext3 @j @S is unknown type %N (unsupported).\n"
10266              "It is likely that your copy of e2fsck is old and/or doesn't "
10267              "support this @j format.\n"
10268              "It is also possible the @j @S is corrupt.\n"),
10269           PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
10270
10271         /* Journal superblock is corrupt */
10272         { PR_0_JOURNAL_BAD_SUPER,
10273           N_("Ext3 @j @S is corrupt.\n"),
10274           PROMPT_FIX, PR_PREEN_OK },
10275
10276         /* Superblock flag should be cleared */
10277         { PR_0_JOURNAL_HAS_JOURNAL,
10278           N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
10279           PROMPT_CLEAR, PR_PREEN_OK },
10280
10281         /* Superblock flag is incorrect */
10282         { PR_0_JOURNAL_RECOVER_SET,
10283           N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
10284           PROMPT_CLEAR, PR_PREEN_OK },
10285
10286         /* Journal has data, but recovery flag is clear */
10287         { PR_0_JOURNAL_RECOVERY_CLEAR,
10288           N_("ext3 recovery flag clear, but @j has data.\n"),
10289           PROMPT_NONE, 0 },
10290
10291         /* Ask if we should clear the journal */
10292         { PR_0_JOURNAL_RESET_JOURNAL,
10293           N_("Clear @j"),
10294           PROMPT_NULL, PR_PREEN_NOMSG },
10295
10296         /* Ask if we should run the journal anyway */
10297         { PR_0_JOURNAL_RUN,
10298           N_("Run @j anyway"),
10299           PROMPT_NULL, 0 },
10300
10301         /* Run the journal by default */
10302         { PR_0_JOURNAL_RUN_DEFAULT,
10303           N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
10304           PROMPT_NONE, 0 },
10305
10306         /* Clearing orphan inode */
10307         { PR_0_ORPHAN_CLEAR_INODE,
10308           N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
10309           PROMPT_NONE, 0 },
10310
10311         /* Illegal block found in orphaned inode */
10312         { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
10313            N_("@I @b #%B (%b) found in @o @i %i.\n"),
10314           PROMPT_NONE, 0 },
10315
10316         /* Already cleared block found in orphaned inode */
10317         { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
10318            N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
10319           PROMPT_NONE, 0 },
10320
10321         /* Illegal orphan inode in superblock */
10322         { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
10323           N_("@I @o @i %i in @S.\n"),
10324           PROMPT_NONE, 0 },
10325
10326         /* Illegal inode in orphaned inode list */
10327         { PR_0_ORPHAN_ILLEGAL_INODE,
10328           N_("@I @i %i in @o @i list.\n"),
10329           PROMPT_NONE, 0 },
10330
10331         /* Filesystem revision is 0, but feature flags are set */
10332         { PR_0_FS_REV_LEVEL,
10333           "@f has feature flag(s) set, but is a revision 0 @f.  ",
10334           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
10335
10336         /* Journal superblock has an unknown read-only feature flag set */
10337         { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
10338           N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
10339           PROMPT_ABORT, 0 },
10340
10341         /* Journal superblock has an unknown incompatible feature flag set */
10342         { PR_0_JOURNAL_UNSUPP_INCOMPAT,
10343           N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
10344           PROMPT_ABORT, 0 },
10345
10346         /* Journal has unsupported version number */
10347         { PR_0_JOURNAL_UNSUPP_VERSION,
10348           N_("@j version not supported by this e2fsck.\n"),
10349           PROMPT_ABORT, 0 },
10350
10351         /* Moving journal to hidden file */
10352         { PR_0_MOVE_JOURNAL,
10353           N_("Moving @j from /%s to hidden inode.\n\n"),
10354           PROMPT_NONE, 0 },
10355
10356         /* Error moving journal to hidden file */
10357         { PR_0_ERR_MOVE_JOURNAL,
10358           N_("Error moving @j: %m\n\n"),
10359           PROMPT_NONE, 0 },
10360
10361         /* Clearing V2 journal superblock */
10362         { PR_0_CLEAR_V2_JOURNAL,
10363           N_("Found invalid V2 @j @S fields (from V1 journal).\n"
10364              "Clearing fields beyond the V1 @j @S...\n\n"),
10365           PROMPT_NONE, 0 },
10366
10367         /* Backup journal inode blocks */
10368         { PR_0_BACKUP_JNL,
10369           N_("Backing up @j @i @b information.\n\n"),
10370           PROMPT_NONE, 0 },
10371
10372         /* Reserved blocks w/o resize_inode */
10373         { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
10374           N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
10375              "is %N; @s zero.  "),
10376           PROMPT_FIX, 0 },
10377
10378         /* Resize_inode not enabled, but resize inode is non-zero */
10379         { PR_0_CLEAR_RESIZE_INODE,
10380           N_("Resize_@i not enabled, but the resize inode is non-zero.  "),
10381           PROMPT_CLEAR, 0 },
10382
10383         /* Resize inode invalid */
10384         { PR_0_RESIZE_INODE_INVALID,
10385           N_("Resize @i not valid.  "),
10386           PROMPT_RECREATE, 0 },
10387
10388         /* Pass 1 errors */
10389
10390         /* Pass 1: Checking inodes, blocks, and sizes */
10391         { PR_1_PASS_HEADER,
10392           N_("Pass 1: Checking @is, @bs, and sizes\n"),
10393           PROMPT_NONE, 0 },
10394
10395         /* Root directory is not an inode */
10396         { PR_1_ROOT_NO_DIR, N_("@r is not a @d.  "),
10397           PROMPT_CLEAR, 0 },
10398
10399         /* Root directory has dtime set */
10400         { PR_1_ROOT_DTIME,
10401           N_("@r has dtime set (probably due to old mke2fs).  "),
10402           PROMPT_FIX, PR_PREEN_OK },
10403
10404         /* Reserved inode has bad mode */
10405         { PR_1_RESERVED_BAD_MODE,
10406           N_("Reserved @i %i %Q has bad mode.  "),
10407           PROMPT_CLEAR, PR_PREEN_OK },
10408
10409         /* Deleted inode has zero dtime */
10410         { PR_1_ZERO_DTIME,
10411           N_("@D @i %i has zero dtime.  "),
10412           PROMPT_FIX, PR_PREEN_OK },
10413
10414         /* Inode in use, but dtime set */
10415         { PR_1_SET_DTIME,
10416           N_("@i %i is in use, but has dtime set.  "),
10417           PROMPT_FIX, PR_PREEN_OK },
10418
10419         /* Zero-length directory */
10420         { PR_1_ZERO_LENGTH_DIR,
10421           N_("@i %i is a @z @d.  "),
10422           PROMPT_CLEAR, PR_PREEN_OK },
10423
10424         /* Block bitmap conflicts with some other fs block */
10425         { PR_1_BB_CONFLICT,
10426           N_("@g %g's @b @B at %b @C.\n"),
10427           PROMPT_RELOCATE, 0 },
10428
10429         /* Inode bitmap conflicts with some other fs block */
10430         { PR_1_IB_CONFLICT,
10431           N_("@g %g's @i @B at %b @C.\n"),
10432           PROMPT_RELOCATE, 0 },
10433
10434         /* Inode table conflicts with some other fs block */
10435         { PR_1_ITABLE_CONFLICT,
10436           N_("@g %g's @i table at %b @C.\n"),
10437           PROMPT_RELOCATE, 0 },
10438
10439         /* Block bitmap is on a bad block */
10440         { PR_1_BB_BAD_BLOCK,
10441           N_("@g %g's @b @B (%b) is bad.  "),
10442           PROMPT_RELOCATE, 0 },
10443
10444         /* Inode bitmap is on a bad block */
10445         { PR_1_IB_BAD_BLOCK,
10446           N_("@g %g's @i @B (%b) is bad.  "),
10447           PROMPT_RELOCATE, 0 },
10448
10449         /* Inode has incorrect i_size */
10450         { PR_1_BAD_I_SIZE,
10451           N_("@i %i, i_size is %Is, @s %N.  "),
10452           PROMPT_FIX, PR_PREEN_OK },
10453
10454         /* Inode has incorrect i_blocks */
10455         { PR_1_BAD_I_BLOCKS,
10456           N_("@i %i, i_@bs is %Ib, @s %N.  "),
10457           PROMPT_FIX, PR_PREEN_OK },
10458
10459         /* Illegal blocknumber in inode */
10460         { PR_1_ILLEGAL_BLOCK_NUM,
10461           N_("@I @b #%B (%b) in @i %i.  "),
10462           PROMPT_CLEAR, PR_LATCH_BLOCK },
10463
10464         /* Block number overlaps fs metadata */
10465         { PR_1_BLOCK_OVERLAPS_METADATA,
10466           N_("@b #%B (%b) overlaps @f metadata in @i %i.  "),
10467           PROMPT_CLEAR, PR_LATCH_BLOCK },
10468
10469         /* Inode has illegal blocks (latch question) */
10470         { PR_1_INODE_BLOCK_LATCH,
10471           N_("@i %i has illegal @b(s).  "),
10472           PROMPT_CLEAR, 0 },
10473
10474         /* Too many bad blocks in inode */
10475         { PR_1_TOO_MANY_BAD_BLOCKS,
10476           N_("Too many illegal @bs in @i %i.\n"),
10477           PROMPT_CLEAR_INODE, PR_NO_OK },
10478
10479         /* Illegal block number in bad block inode */
10480         { PR_1_BB_ILLEGAL_BLOCK_NUM,
10481           N_("@I @b #%B (%b) in bad @b @i.  "),
10482           PROMPT_CLEAR, PR_LATCH_BBLOCK },
10483
10484         /* Bad block inode has illegal blocks (latch question) */
10485         { PR_1_INODE_BBLOCK_LATCH,
10486           N_("Bad @b @i has illegal @b(s).  "),
10487           PROMPT_CLEAR, 0 },
10488
10489         /* Duplicate or bad blocks in use! */
10490         { PR_1_DUP_BLOCKS_PREENSTOP,
10491           N_("Duplicate or bad @b in use!\n"),
10492           PROMPT_NONE, 0 },
10493
10494         /* Bad block used as bad block indirect block */
10495         { PR_1_BBINODE_BAD_METABLOCK,
10496           N_("Bad @b %b used as bad @b @i indirect @b.  "),
10497           PROMPT_CLEAR, PR_LATCH_BBLOCK },
10498
10499         /* Inconsistency can't be fixed prompt */
10500         { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
10501           N_("\nThe bad @b @i has probably been corrupted.  You probably\n"
10502              "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
10503              "in the @f.\n"),
10504           PROMPT_CONTINUE, PR_PREEN_NOMSG },
10505
10506         /* Bad primary block */
10507         { PR_1_BAD_PRIMARY_BLOCK,
10508           N_("\nIf the @b is really bad, the @f can not be fixed.\n"),
10509           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
10510
10511         /* Bad primary block prompt */
10512         { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
10513           N_("You can clear the this @b (and hope for the best) from the\n"
10514           "bad @b list and hope that @b is really OK, but there are no\n"
10515           "guarantees.\n\n"),
10516           PROMPT_CLEAR, PR_PREEN_NOMSG },
10517
10518         /* Bad primary superblock */
10519         { PR_1_BAD_PRIMARY_SUPERBLOCK,
10520           N_("The primary @S (%b) is on the bad @b list.\n"),
10521           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
10522
10523         /* Bad primary block group descriptors */
10524         { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
10525           N_("Block %b in the primary @g descriptors "
10526           "is on the bad @b list\n"),
10527           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
10528
10529         /* Bad superblock in group */
10530         { PR_1_BAD_SUPERBLOCK,
10531           N_("Warning: Group %g's @S (%b) is bad.\n"),
10532           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
10533
10534         /* Bad block group descriptors in group */
10535         { PR_1_BAD_GROUP_DESCRIPTORS,
10536           N_("Warning: Group %g's copy of the @g descriptors has a bad "
10537           "@b (%b).\n"),
10538           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
10539
10540         /* Block claimed for no reason */
10541         { PR_1_PROGERR_CLAIMED_BLOCK,
10542           N_("Programming error?  @b #%b claimed for no reason in "
10543           "process_bad_@b.\n"),
10544           PROMPT_NONE, PR_PREEN_OK },
10545
10546         /* Error allocating blocks for relocating metadata */
10547         { PR_1_RELOC_BLOCK_ALLOCATE,
10548           N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
10549           PROMPT_NONE, PR_PREEN_OK },
10550
10551         /* Error allocating block buffer during relocation process */
10552         { PR_1_RELOC_MEMORY_ALLOCATE,
10553           N_("@A @b buffer for relocating %s\n"),
10554           PROMPT_NONE, PR_PREEN_OK },
10555
10556         /* Relocating metadata group information from X to Y */
10557         { PR_1_RELOC_FROM_TO,
10558           N_("Relocating @g %g's %s from %b to %c...\n"),
10559           PROMPT_NONE, PR_PREEN_OK },
10560
10561         /* Relocating metatdata group information to X */
10562         { PR_1_RELOC_TO,
10563           N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
10564           PROMPT_NONE, PR_PREEN_OK },
10565
10566         /* Block read error during relocation process */
10567         { PR_1_RELOC_READ_ERR,
10568           N_("Warning: could not read @b %b of %s: %m\n"),
10569           PROMPT_NONE, PR_PREEN_OK },
10570
10571         /* Block write error during relocation process */
10572         { PR_1_RELOC_WRITE_ERR,
10573           N_("Warning: could not write @b %b for %s: %m\n"),
10574           PROMPT_NONE, PR_PREEN_OK },
10575
10576         /* Error allocating inode bitmap */
10577         { PR_1_ALLOCATE_IBITMAP_ERROR,
10578           "@A @i @B (%N): %m\n",
10579           PROMPT_NONE, PR_FATAL },
10580
10581         /* Error allocating block bitmap */
10582         { PR_1_ALLOCATE_BBITMAP_ERROR,
10583           "@A @b @B (%N): %m\n",
10584           PROMPT_NONE, PR_FATAL },
10585
10586         /* Error allocating icount structure */
10587         { PR_1_ALLOCATE_ICOUNT,
10588           N_("@A icount link information: %m\n"),
10589           PROMPT_NONE, PR_FATAL },
10590
10591         /* Error allocating dbcount */
10592         { PR_1_ALLOCATE_DBCOUNT,
10593           N_("@A @d @b array: %m\n"),
10594           PROMPT_NONE, PR_FATAL },
10595
10596         /* Error while scanning inodes */
10597         { PR_1_ISCAN_ERROR,
10598           N_("Error while scanning @is (%i): %m\n"),
10599           PROMPT_NONE, PR_FATAL },
10600
10601         /* Error while iterating over blocks */
10602         { PR_1_BLOCK_ITERATE,
10603           N_("Error while iterating over @bs in @i %i: %m\n"),
10604           PROMPT_NONE, PR_FATAL },
10605
10606         /* Error while storing inode count information */
10607         { PR_1_ICOUNT_STORE,
10608           N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
10609           PROMPT_NONE, PR_FATAL },
10610
10611         /* Error while storing directory block information */
10612         { PR_1_ADD_DBLOCK,
10613           N_("Error storing @d @b information "
10614           "(@i=%i, @b=%b, num=%N): %m\n"),
10615           PROMPT_NONE, PR_FATAL },
10616
10617         /* Error while reading inode (for clearing) */
10618         { PR_1_READ_INODE,
10619           N_("Error reading @i %i: %m\n"),
10620           PROMPT_NONE, PR_FATAL },
10621
10622         /* Suppress messages prompt */
10623         { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
10624
10625         /* Imagic flag set on an inode when filesystem doesn't support it */
10626         { PR_1_SET_IMAGIC,
10627           N_("@i %i has imagic flag set.  "),
10628           PROMPT_CLEAR, 0 },
10629
10630         /* Immutable flag set on a device or socket inode */
10631         { PR_1_SET_IMMUTABLE,
10632           N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
10633              "or append-only flag set.  "),
10634           PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
10635
10636         /* Compression flag set on an inode when filesystem doesn't support it */
10637         { PR_1_COMPR_SET,
10638           N_("@i %i has @cion flag set on @f without @cion support.  "),
10639           PROMPT_CLEAR, 0 },
10640
10641         /* Non-zero size for device, fifo or socket inode */
10642         { PR_1_SET_NONZSIZE,
10643           "Special (@v/socket/fifo) @i %i has non-zero size.  ",
10644           PROMPT_FIX, PR_PREEN_OK },
10645
10646         /* Filesystem revision is 0, but feature flags are set */
10647         { PR_1_FS_REV_LEVEL,
10648           "@f has feature flag(s) set, but is a revision 0 @f.  ",
10649           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
10650
10651         /* Journal inode is not in use, but contains data */
10652         { PR_1_JOURNAL_INODE_NOT_CLEAR,
10653           "@j @i is not in use, but contains data.  ",
10654           PROMPT_CLEAR, PR_PREEN_OK },
10655
10656         /* Journal has bad mode */
10657         { PR_1_JOURNAL_BAD_MODE,
10658           N_("@j is not regular file.  "),
10659           PROMPT_FIX, PR_PREEN_OK },
10660
10661         /* Deal with inodes that were part of orphan linked list */
10662         { PR_1_LOW_DTIME,
10663           N_("@i %i was part of the orphaned @i list.  "),
10664           PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
10665
10666         /* Deal with inodes that were part of corrupted orphan linked
10667            list (latch question) */
10668         { PR_1_ORPHAN_LIST_REFUGEES,
10669           N_("@is that were part of a corrupted orphan linked list found.  "),
10670           PROMPT_FIX, 0 },
10671
10672         /* Error allocating refcount structure */
10673         { PR_1_ALLOCATE_REFCOUNT,
10674           "@A refcount structure (%N): %m\n",
10675           PROMPT_NONE, PR_FATAL },
10676
10677         /* Error reading extended attribute block */
10678         { PR_1_READ_EA_BLOCK,
10679           N_("Error reading @a @b %b for @i %i.  "),
10680           PROMPT_CLEAR, 0 },
10681
10682         /* Invalid extended attribute block */
10683         { PR_1_BAD_EA_BLOCK,
10684           N_("@i %i has a bad @a @b %b.  "),
10685           PROMPT_CLEAR, 0 },
10686
10687         /* Error reading Extended Attribute block while fixing refcount */
10688         { PR_1_EXTATTR_READ_ABORT,
10689           N_("Error reading @a @b %b (%m).  "),
10690           PROMPT_ABORT, 0 },
10691
10692         /* Extended attribute reference count incorrect */
10693         { PR_1_EXTATTR_REFCOUNT,
10694           N_("@a @b %b has reference count %B, should be %N.  "),
10695           PROMPT_FIX, 0 },
10696
10697         /* Error writing Extended Attribute block while fixing refcount */
10698         { PR_1_EXTATTR_WRITE,
10699           N_("Error writing @a @b %b (%m).  "),
10700           PROMPT_ABORT, 0 },
10701
10702         /* Multiple EA blocks not supported */
10703         { PR_1_EA_MULTI_BLOCK,
10704           N_("@a @b %b has h_blocks > 1.  "),
10705           PROMPT_CLEAR, 0},
10706
10707         /* Error allocating EA region allocation structure */
10708         { PR_1_EA_ALLOC_REGION,
10709           N_("Error allocating @a @b %b.  "),
10710           PROMPT_ABORT, 0},
10711
10712         /* Error EA allocation collision */
10713         { PR_1_EA_ALLOC_COLLISION,
10714           N_("@a @b %b is corrupt (allocation collision).  "),
10715           PROMPT_CLEAR, 0},
10716
10717         /* Bad extended attribute name */
10718         { PR_1_EA_BAD_NAME,
10719           N_("@a @b %b is corrupt (invalid name).  "),
10720           PROMPT_CLEAR, 0},
10721
10722         /* Bad extended attribute value */
10723         { PR_1_EA_BAD_VALUE,
10724           N_("@a @b %b is corrupt (invalid value).  "),
10725           PROMPT_CLEAR, 0},
10726
10727         /* Inode too big (latch question) */
10728         { PR_1_INODE_TOOBIG,
10729           N_("@i %i is too big.  "), PROMPT_TRUNCATE, 0 },
10730
10731         /* Directory too big */
10732         { PR_1_TOOBIG_DIR,
10733           N_("@b #%B (%b) causes @d to be too big.  "),
10734           PROMPT_CLEAR, PR_LATCH_TOOBIG },
10735
10736         /* Regular file too big */
10737         { PR_1_TOOBIG_REG,
10738           N_("@b #%B (%b) causes file to be too big.  "),
10739           PROMPT_CLEAR, PR_LATCH_TOOBIG },
10740
10741         /* Symlink too big */
10742         { PR_1_TOOBIG_SYMLINK,
10743           N_("@b #%B (%b) causes symlink to be too big.  "),
10744           PROMPT_CLEAR, PR_LATCH_TOOBIG },
10745
10746         /* INDEX_FL flag set on a non-HTREE filesystem */
10747         { PR_1_HTREE_SET,
10748           N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
10749           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10750
10751         /* INDEX_FL flag set on a non-directory */
10752         { PR_1_HTREE_NODIR,
10753           N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
10754           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10755
10756         /* Invalid root node in HTREE directory */
10757         { PR_1_HTREE_BADROOT,
10758           N_("@h %i has an invalid root node.\n"),
10759           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10760
10761         /* Unsupported hash version in HTREE directory */
10762         { PR_1_HTREE_HASHV,
10763           N_("@h %i has an unsupported hash version (%N)\n"),
10764           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10765
10766         /* Incompatible flag in HTREE root node */
10767         { PR_1_HTREE_INCOMPAT,
10768           N_("@h %i uses an incompatible htree root node flag.\n"),
10769           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10770
10771         /* HTREE too deep */
10772         { PR_1_HTREE_DEPTH,
10773           N_("@h %i has a tree depth (%N) which is too big\n"),
10774           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10775
10776         /* Bad block has indirect block that conflicts with filesystem block */
10777         { PR_1_BB_FS_BLOCK,
10778           N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
10779              "@f metadata.  "),
10780           PROMPT_CLEAR, PR_LATCH_BBLOCK },
10781
10782         /* Resize inode failed */
10783         { PR_1_RESIZE_INODE_CREATE,
10784           N_("Resize @i (re)creation failed: %m."),
10785           PROMPT_ABORT, 0 },
10786
10787         /* invalid inode->i_extra_isize */
10788         { PR_1_EXTRA_ISIZE,
10789           N_("@i %i has a extra size (%IS) which is invalid\n"),
10790           PROMPT_FIX, PR_PREEN_OK },
10791
10792         /* invalid ea entry->e_name_len */
10793         { PR_1_ATTR_NAME_LEN,
10794           N_("@a in @i %i has a namelen (%N) which is invalid\n"),
10795           PROMPT_CLEAR, PR_PREEN_OK },
10796
10797         /* invalid ea entry->e_value_size */
10798         { PR_1_ATTR_VALUE_SIZE,
10799           N_("@a in @i %i has a value size (%N) which is invalid\n"),
10800           PROMPT_CLEAR, PR_PREEN_OK },
10801
10802         /* invalid ea entry->e_value_offs */
10803         { PR_1_ATTR_VALUE_OFFSET,
10804           N_("@a in @i %i has a value offset (%N) which is invalid\n"),
10805           PROMPT_CLEAR, PR_PREEN_OK },
10806
10807         /* invalid ea entry->e_value_block */
10808         { PR_1_ATTR_VALUE_BLOCK,
10809           N_("@a in @i %i has a value block (%N) which is invalid (must be 0)\n"),
10810           PROMPT_CLEAR, PR_PREEN_OK },
10811
10812         /* invalid ea entry->e_hash */
10813         { PR_1_ATTR_HASH,
10814           N_("@a in @i %i has a hash (%N) which is invalid (must be 0)\n"),
10815           PROMPT_CLEAR, PR_PREEN_OK },
10816
10817         /* Pass 1b errors */
10818
10819         /* Pass 1B: Rescan for duplicate/bad blocks */
10820         { PR_1B_PASS_HEADER,
10821           N_("Duplicate @bs found... invoking duplicate @b passes.\n"
10822           "Pass 1B: Rescan for duplicate/bad @bs\n"),
10823           PROMPT_NONE, 0 },
10824
10825         /* Duplicate/bad block(s) header */
10826         { PR_1B_DUP_BLOCK_HEADER,
10827           N_("Duplicate/bad @b(s) in @i %i:"),
10828           PROMPT_NONE, 0 },
10829
10830         /* Duplicate/bad block(s) in inode */
10831         { PR_1B_DUP_BLOCK,
10832           " %b",
10833           PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
10834
10835         /* Duplicate/bad block(s) end */
10836         { PR_1B_DUP_BLOCK_END,
10837           "\n",
10838           PROMPT_NONE, PR_PREEN_NOHDR },
10839
10840         /* Error while scanning inodes */
10841         { PR_1B_ISCAN_ERROR,
10842           N_("Error while scanning inodes (%i): %m\n"),
10843           PROMPT_NONE, PR_FATAL },
10844
10845         /* Error allocating inode bitmap */
10846         { PR_1B_ALLOCATE_IBITMAP_ERROR,
10847           N_("@A @i @B (inode_dup_map): %m\n"),
10848           PROMPT_NONE, PR_FATAL },
10849
10850         /* Error while iterating over blocks */
10851         { PR_1B_BLOCK_ITERATE,
10852           N_("Error while iterating over @bs in @i %i (%s): %m\n"),
10853           PROMPT_NONE, 0 },
10854
10855         /* Error adjusting EA refcount */
10856         { PR_1B_ADJ_EA_REFCOUNT,
10857           N_("Error addjusting refcount for @a @b %b (@i %i): %m\n"),
10858           PROMPT_NONE, 0 },
10859
10860
10861         /* Pass 1C: Scan directories for inodes with dup blocks. */
10862         { PR_1C_PASS_HEADER,
10863           N_("Pass 1C: Scan directories for @is with dup @bs.\n"),
10864           PROMPT_NONE, 0 },
10865
10866
10867         /* Pass 1D: Reconciling duplicate blocks */
10868         { PR_1D_PASS_HEADER,
10869           N_("Pass 1D: Reconciling duplicate @bs\n"),
10870           PROMPT_NONE, 0 },
10871
10872         /* File has duplicate blocks */
10873         { PR_1D_DUP_FILE,
10874           N_("File %Q (@i #%i, mod time %IM) \n"
10875           "  has %B duplicate @b(s), shared with %N file(s):\n"),
10876           PROMPT_NONE, 0 },
10877
10878         /* List of files sharing duplicate blocks */
10879         { PR_1D_DUP_FILE_LIST,
10880           N_("\t%Q (@i #%i, mod time %IM)\n"),
10881           PROMPT_NONE, 0 },
10882
10883         /* File sharing blocks with filesystem metadata  */
10884         { PR_1D_SHARE_METADATA,
10885           N_("\t<@f metadata>\n"),
10886           PROMPT_NONE, 0 },
10887
10888         /* Report of how many duplicate/bad inodes */
10889         { PR_1D_NUM_DUP_INODES,
10890           N_("(There are %N @is containing duplicate/bad @bs.)\n\n"),
10891           PROMPT_NONE, 0 },
10892
10893         /* Duplicated blocks already reassigned or cloned. */
10894         { PR_1D_DUP_BLOCKS_DEALT,
10895           N_("Duplicated @bs already reassigned or cloned.\n\n"),
10896           PROMPT_NONE, 0 },
10897
10898         /* Clone duplicate/bad blocks? */
10899         { PR_1D_CLONE_QUESTION,
10900           "", PROMPT_CLONE, PR_NO_OK },
10901
10902         /* Delete file? */
10903         { PR_1D_DELETE_QUESTION,
10904           "", PROMPT_DELETE, 0 },
10905
10906         /* Couldn't clone file (error) */
10907         { PR_1D_CLONE_ERROR,
10908           N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
10909
10910         /* Pass 2 errors */
10911
10912         /* Pass 2: Checking directory structure */
10913         { PR_2_PASS_HEADER,
10914           N_("Pass 2: Checking @d structure\n"),
10915           PROMPT_NONE, 0 },
10916
10917         /* Bad inode number for '.' */
10918         { PR_2_BAD_INODE_DOT,
10919           N_("Bad @i number for '.' in @d @i %i.\n"),
10920           PROMPT_FIX, 0 },
10921
10922         /* Directory entry has bad inode number */
10923         { PR_2_BAD_INO,
10924           N_("@E has bad @i #: %Di.\n"),
10925           PROMPT_CLEAR, 0 },
10926
10927         /* Directory entry has deleted or unused inode */
10928         { PR_2_UNUSED_INODE,
10929           N_("@E has @D/unused @i %Di.  "),
10930           PROMPT_CLEAR, PR_PREEN_OK },
10931
10932         /* Directry entry is link to '.' */
10933         { PR_2_LINK_DOT,
10934           N_("@E @L to '.'  "),
10935           PROMPT_CLEAR, 0 },
10936
10937         /* Directory entry points to inode now located in a bad block */
10938         { PR_2_BB_INODE,
10939           N_("@E points to @i (%Di) located in a bad @b.\n"),
10940           PROMPT_CLEAR, 0 },
10941
10942         /* Directory entry contains a link to a directory */
10943         { PR_2_LINK_DIR,
10944           N_("@E @L to @d %P (%Di).\n"),
10945           PROMPT_CLEAR, 0 },
10946
10947         /* Directory entry contains a link to the root directry */
10948         { PR_2_LINK_ROOT,
10949           N_("@E @L to the @r.\n"),
10950           PROMPT_CLEAR, 0 },
10951
10952         /* Directory entry has illegal characters in its name */
10953         { PR_2_BAD_NAME,
10954           N_("@E has illegal characters in its name.\n"),
10955           PROMPT_FIX, 0 },
10956
10957         /* Missing '.' in directory inode */
10958         { PR_2_MISSING_DOT,
10959           N_("Missing '.' in @d @i %i.\n"),
10960           PROMPT_FIX, 0 },
10961
10962         /* Missing '..' in directory inode */
10963         { PR_2_MISSING_DOT_DOT,
10964           N_("Missing '..' in @d @i %i.\n"),
10965           PROMPT_FIX, 0 },
10966
10967         /* First entry in directory inode doesn't contain '.' */
10968         { PR_2_1ST_NOT_DOT,
10969           N_("First @e '%Dn' (inode=%Di) in @d @i %i (%p) @s '.'\n"),
10970           PROMPT_FIX, 0 },
10971
10972         /* Second entry in directory inode doesn't contain '..' */
10973         { PR_2_2ND_NOT_DOT_DOT,
10974           N_("Second @e '%Dn' (inode=%Di) in @d @i %i @s '..'\n"),
10975           PROMPT_FIX, 0 },
10976
10977         /* i_faddr should be zero */
10978         { PR_2_FADDR_ZERO,
10979           N_("i_faddr @F %IF, @s zero.\n"),
10980           PROMPT_CLEAR, 0 },
10981
10982         /* i_file_acl should be zero */
10983         { PR_2_FILE_ACL_ZERO,
10984           N_("i_file_acl @F %If, @s zero.\n"),
10985           PROMPT_CLEAR, 0 },
10986
10987         /* i_dir_acl should be zero */
10988         { PR_2_DIR_ACL_ZERO,
10989           N_("i_dir_acl @F %Id, @s zero.\n"),
10990           PROMPT_CLEAR, 0 },
10991
10992         /* i_frag should be zero */
10993         { PR_2_FRAG_ZERO,
10994           N_("i_frag @F %N, @s zero.\n"),
10995           PROMPT_CLEAR, 0 },
10996
10997         /* i_fsize should be zero */
10998         { PR_2_FSIZE_ZERO,
10999           N_("i_fsize @F %N, @s zero.\n"),
11000           PROMPT_CLEAR, 0 },
11001
11002         /* inode has bad mode */
11003         { PR_2_BAD_MODE,
11004           N_("@i %i (%Q) has a bad mode (%Im).\n"),
11005           PROMPT_CLEAR, 0 },
11006
11007         /* directory corrupted */
11008         { PR_2_DIR_CORRUPTED,
11009           N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
11010           PROMPT_SALVAGE, 0 },
11011
11012         /* filename too long */
11013         { PR_2_FILENAME_LONG,
11014           N_("@d @i %i, @b %B, offset %N: filename too long\n"),
11015           PROMPT_TRUNCATE, 0 },
11016
11017         /* Directory inode has a missing block (hole) */
11018         { PR_2_DIRECTORY_HOLE,
11019           N_("@d @i %i has an unallocated @b #%B.  "),
11020           PROMPT_ALLOCATE, 0 },
11021
11022         /* '.' is not NULL terminated */
11023         { PR_2_DOT_NULL_TERM,
11024           N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
11025           PROMPT_FIX, 0 },
11026
11027         /* '..' is not NULL terminated */
11028         { PR_2_DOT_DOT_NULL_TERM,
11029           N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
11030           PROMPT_FIX, 0 },
11031
11032         /* Illegal character device inode */
11033         { PR_2_BAD_CHAR_DEV,
11034           N_("@i %i (%Q) is an @I character @v.\n"),
11035           PROMPT_CLEAR, 0 },
11036
11037         /* Illegal block device inode */
11038         { PR_2_BAD_BLOCK_DEV,
11039           N_("@i %i (%Q) is an @I @b @v.\n"),
11040           PROMPT_CLEAR, 0 },
11041
11042         /* Duplicate '.' entry */
11043         { PR_2_DUP_DOT,
11044           N_("@E is duplicate '.' @e.\n"),
11045           PROMPT_FIX, 0 },
11046
11047         /* Duplicate '..' entry */
11048         { PR_2_DUP_DOT_DOT,
11049           N_("@E is duplicate '..' @e.\n"),
11050           PROMPT_FIX, 0 },
11051
11052         /* Internal error: couldn't find dir_info */
11053         { PR_2_NO_DIRINFO,
11054           N_("Internal error: couldn't find dir_info for %i.\n"),
11055           PROMPT_NONE, PR_FATAL },
11056
11057         /* Final rec_len is wrong */
11058         { PR_2_FINAL_RECLEN,
11059           N_("@E has rec_len of %Dr, should be %N.\n"),
11060           PROMPT_FIX, 0 },
11061
11062         /* Error allocating icount structure */
11063         { PR_2_ALLOCATE_ICOUNT,
11064           N_("@A icount structure: %m\n"),
11065           PROMPT_NONE, PR_FATAL },
11066
11067         /* Error iterating over directory blocks */
11068         { PR_2_DBLIST_ITERATE,
11069           N_("Error iterating over @d @bs: %m\n"),
11070           PROMPT_NONE, PR_FATAL },
11071
11072         /* Error reading directory block */
11073         { PR_2_READ_DIRBLOCK,
11074           N_("Error reading @d @b %b (@i %i): %m\n"),
11075           PROMPT_CONTINUE, 0 },
11076
11077         /* Error writing directory block */
11078         { PR_2_WRITE_DIRBLOCK,
11079           N_("Error writing @d @b %b (@i %i): %m\n"),
11080           PROMPT_CONTINUE, 0 },
11081
11082         /* Error allocating new directory block */
11083         { PR_2_ALLOC_DIRBOCK,
11084           N_("@A new @d @b for @i %i (%s): %m\n"),
11085           PROMPT_NONE, 0 },
11086
11087         /* Error deallocating inode */
11088         { PR_2_DEALLOC_INODE,
11089           N_("Error deallocating @i %i: %m\n"),
11090           PROMPT_NONE, PR_FATAL },
11091
11092         /* Directory entry for '.' is big.  Split? */
11093         { PR_2_SPLIT_DOT,
11094           N_("@d @e for '.' is big.  "),
11095           PROMPT_SPLIT, PR_NO_OK },
11096
11097         /* Illegal FIFO inode */
11098         { PR_2_BAD_FIFO,
11099           N_("@i %i (%Q) is an @I FIFO.\n"),
11100           PROMPT_CLEAR, 0 },
11101
11102         /* Illegal socket inode */
11103         { PR_2_BAD_SOCKET,
11104           N_("@i %i (%Q) is an @I socket.\n"),
11105           PROMPT_CLEAR, 0 },
11106
11107         /* Directory filetype not set */
11108         { PR_2_SET_FILETYPE,
11109           N_("Setting filetype for @E to %N.\n"),
11110           PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
11111
11112         /* Directory filetype incorrect */
11113         { PR_2_BAD_FILETYPE,
11114           N_("@E has an incorrect filetype (was %Dt, should be %N).\n"),
11115           PROMPT_FIX, 0 },
11116
11117         /* Directory filetype set on filesystem */
11118         { PR_2_CLEAR_FILETYPE,
11119           N_("@E has filetype set.\n"),
11120           PROMPT_CLEAR, PR_PREEN_OK },
11121
11122         /* Directory filename is null */
11123         { PR_2_NULL_NAME,
11124           N_("@E has a zero-length name.\n"),
11125           PROMPT_CLEAR, 0 },
11126
11127         /* Invalid symlink */
11128         { PR_2_INVALID_SYMLINK,
11129           N_("Symlink %Q (@i #%i) is invalid.\n"),
11130           PROMPT_CLEAR, 0 },
11131
11132         /* i_file_acl (extended attribute block) is bad */
11133         { PR_2_FILE_ACL_BAD,
11134           N_("@a @b @F invalid (%If).\n"),
11135           PROMPT_CLEAR, 0 },
11136
11137         /* Filesystem contains large files, but has no such flag in sb */
11138         { PR_2_FEATURE_LARGE_FILES,
11139           N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
11140           PROMPT_FIX, 0 },
11141
11142         /* Node in HTREE directory not referenced */
11143         { PR_2_HTREE_NOTREF,
11144           N_("@p @h %d: node (%B) not referenced\n"),
11145           PROMPT_NONE, 0 },
11146
11147         /* Node in HTREE directory referenced twice */
11148         { PR_2_HTREE_DUPREF,
11149           N_("@p @h %d: node (%B) referenced twice\n"),
11150           PROMPT_NONE, 0 },
11151
11152         /* Node in HTREE directory has bad min hash */
11153         { PR_2_HTREE_MIN_HASH,
11154           N_("@p @h %d: node (%B) has bad min hash\n"),
11155           PROMPT_NONE, 0 },
11156
11157         /* Node in HTREE directory has bad max hash */
11158         { PR_2_HTREE_MAX_HASH,
11159           N_("@p @h %d: node (%B) has bad max hash\n"),
11160           PROMPT_NONE, 0 },
11161
11162         /* Clear invalid HTREE directory */
11163         { PR_2_HTREE_CLEAR,
11164           N_("Invalid @h %d (%q).  "), PROMPT_CLEAR, 0 },
11165
11166         /* Bad block in htree interior node */
11167         { PR_2_HTREE_BADBLK,
11168           N_("@p @h %d (%q): bad @b number %b.\n"),
11169           PROMPT_CLEAR_HTREE, 0 },
11170
11171         /* Error adjusting EA refcount */
11172         { PR_2_ADJ_EA_REFCOUNT,
11173           N_("Error addjusting refcount for @a @b %b (@i %i): %m\n"),
11174           PROMPT_NONE, PR_FATAL },
11175
11176         /* Invalid HTREE root node */
11177         { PR_2_HTREE_BAD_ROOT,
11178           N_("@p @h %d: root node is invalid\n"),
11179           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11180
11181         /* Invalid HTREE limit */
11182         { PR_2_HTREE_BAD_LIMIT,
11183           N_("@p @h %d: node (%B) has bad limit (%N)\n"),
11184           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11185
11186         /* Invalid HTREE count */
11187         { PR_2_HTREE_BAD_COUNT,
11188           N_("@p @h %d: node (%B) has bad count (%N)\n"),
11189           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11190
11191         /* HTREE interior node has out-of-order hashes in table */
11192         { PR_2_HTREE_HASH_ORDER,
11193           N_("@p @h %d: node (%B) has an unordered hash table\n"),
11194           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11195
11196         /* Node in HTREE directory has bad depth */
11197         { PR_2_HTREE_BAD_DEPTH,
11198           N_("@p @h %d: node (%B) has bad depth\n"),
11199           PROMPT_NONE, 0 },
11200
11201         /* Duplicate directory entry found */
11202         { PR_2_DUPLICATE_DIRENT,
11203           N_("Duplicate @E found.  "),
11204           PROMPT_CLEAR, 0 },
11205
11206         /* Non-unique filename found */
11207         { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
11208           N_("@E has a non-unique filename.\nRename to %s"),
11209           PROMPT_NULL, 0 },
11210
11211         /* Duplicate directory entry found */
11212         { PR_2_REPORT_DUP_DIRENT,
11213           N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
11214           PROMPT_NONE, 0 },
11215
11216         /* Pass 3 errors */
11217
11218         /* Pass 3: Checking directory connectivity */
11219         { PR_3_PASS_HEADER,
11220           N_("Pass 3: Checking @d connectivity\n"),
11221           PROMPT_NONE, 0 },
11222
11223         /* Root inode not allocated */
11224         { PR_3_NO_ROOT_INODE,
11225           N_("@r not allocated.  "),
11226           PROMPT_ALLOCATE, 0 },
11227
11228         /* No room in lost+found */
11229         { PR_3_EXPAND_LF_DIR,
11230           N_("No room in @l @d.  "),
11231           PROMPT_EXPAND, 0 },
11232
11233         /* Unconnected directory inode */
11234         { PR_3_UNCONNECTED_DIR,
11235           N_("Unconnected @d @i %i (%p)\n"),
11236           PROMPT_CONNECT, 0 },
11237
11238         /* /lost+found not found */
11239         { PR_3_NO_LF_DIR,
11240           N_("/@l not found.  "),
11241           PROMPT_CREATE, PR_PREEN_OK },
11242
11243         /* .. entry is incorrect */
11244         { PR_3_BAD_DOT_DOT,
11245           N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
11246           PROMPT_FIX, 0 },
11247
11248         /* Bad or non-existent /lost+found.  Cannot reconnect */
11249         { PR_3_NO_LPF,
11250           N_("Bad or non-existent /@l.  Cannot reconnect.\n"),
11251           PROMPT_NONE, 0 },
11252
11253         /* Could not expand /lost+found */
11254         { PR_3_CANT_EXPAND_LPF,
11255           N_("Could not expand /@l: %m\n"),
11256           PROMPT_NONE, 0 },
11257
11258         /* Could not reconnect inode */
11259         { PR_3_CANT_RECONNECT,
11260           N_("Could not reconnect %i: %m\n"),
11261           PROMPT_NONE, 0 },
11262
11263         /* Error while trying to find /lost+found */
11264         { PR_3_ERR_FIND_LPF,
11265           N_("Error while trying to find /@l: %m\n"),
11266           PROMPT_NONE, 0 },
11267
11268         /* Error in ext2fs_new_block while creating /lost+found */
11269         { PR_3_ERR_LPF_NEW_BLOCK,
11270           N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
11271           PROMPT_NONE, 0 },
11272
11273         /* Error in ext2fs_new_inode while creating /lost+found */
11274         { PR_3_ERR_LPF_NEW_INODE,
11275           N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
11276           PROMPT_NONE, 0 },
11277
11278         /* Error in ext2fs_new_dir_block while creating /lost+found */
11279         { PR_3_ERR_LPF_NEW_DIR_BLOCK,
11280           N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
11281           PROMPT_NONE, 0 },
11282
11283         /* Error while writing directory block for /lost+found */
11284         { PR_3_ERR_LPF_WRITE_BLOCK,
11285           N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
11286           PROMPT_NONE, 0 },
11287
11288         /* Error while adjusting inode count */
11289         { PR_3_ADJUST_INODE,
11290           N_("Error while adjusting @i count on @i %i\n"),
11291           PROMPT_NONE, 0 },
11292
11293         /* Couldn't fix parent directory -- error */
11294         { PR_3_FIX_PARENT_ERR,
11295           N_("Couldn't fix parent of @i %i: %m\n\n"),
11296           PROMPT_NONE, 0 },
11297
11298         /* Couldn't fix parent directory -- couldn't find it */
11299         { PR_3_FIX_PARENT_NOFIND,
11300           N_("Couldn't fix parent of @i %i: Couldn't find parent @d entry\n\n"),
11301           PROMPT_NONE, 0 },
11302
11303         /* Error allocating inode bitmap */
11304         { PR_3_ALLOCATE_IBITMAP_ERROR,
11305           N_("@A @i @B (%N): %m\n"),
11306           PROMPT_NONE, PR_FATAL },
11307
11308         /* Error creating root directory */
11309         { PR_3_CREATE_ROOT_ERROR,
11310           N_("Error creating root @d (%s): %m\n"),
11311           PROMPT_NONE, PR_FATAL },
11312
11313         /* Error creating lost and found directory */
11314         { PR_3_CREATE_LPF_ERROR,
11315           N_("Error creating /@l @d (%s): %m\n"),
11316           PROMPT_NONE, PR_FATAL },
11317
11318         /* Root inode is not directory; aborting */
11319         { PR_3_ROOT_NOT_DIR_ABORT,
11320           N_("@r is not a @d; aborting.\n"),
11321           PROMPT_NONE, PR_FATAL },
11322
11323         /* Cannot proceed without a root inode. */
11324         { PR_3_NO_ROOT_INODE_ABORT,
11325           N_("Cannot proceed without a @r.\n"),
11326           PROMPT_NONE, PR_FATAL },
11327
11328         /* Internal error: couldn't find dir_info */
11329         { PR_3_NO_DIRINFO,
11330           N_("Internal error: couldn't find dir_info for %i.\n"),
11331           PROMPT_NONE, PR_FATAL },
11332
11333         /* Lost+found not a directory */
11334         { PR_3_LPF_NOTDIR,
11335           N_("/@l is not a @d (ino=%i)\n"),
11336           PROMPT_UNLINK, 0 },
11337
11338         /* Pass 3A Directory Optimization       */
11339
11340         /* Pass 3A: Optimizing directories */
11341         { PR_3A_PASS_HEADER,
11342           N_("Pass 3A: Optimizing directories\n"),
11343           PROMPT_NONE, PR_PREEN_NOMSG },
11344
11345         /* Error iterating over directories */
11346         { PR_3A_OPTIMIZE_ITER,
11347           N_("Failed to create dirs_to_hash iterator: %m"),
11348           PROMPT_NONE, 0 },
11349
11350         /* Error rehash directory */
11351         { PR_3A_OPTIMIZE_DIR_ERR,
11352           N_("Failed to optimize directory %q (%d): %m"),
11353           PROMPT_NONE, 0 },
11354
11355         /* Rehashing dir header */
11356         { PR_3A_OPTIMIZE_DIR_HEADER,
11357           N_("Optimizing directories: "),
11358           PROMPT_NONE, PR_MSG_ONLY },
11359
11360         /* Rehashing directory %d */
11361         { PR_3A_OPTIMIZE_DIR,
11362           " %d",
11363           PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
11364
11365         /* Rehashing dir end */
11366         { PR_3A_OPTIMIZE_DIR_END,
11367           "\n",
11368           PROMPT_NONE, PR_PREEN_NOHDR },
11369
11370         /* Pass 4 errors */
11371
11372         /* Pass 4: Checking reference counts */
11373         { PR_4_PASS_HEADER,
11374           N_("Pass 4: Checking reference counts\n"),
11375           PROMPT_NONE, 0 },
11376
11377         /* Unattached zero-length inode */
11378         { PR_4_ZERO_LEN_INODE,
11379           "@u @z @i %i.  ",
11380           PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
11381
11382         /* Unattached inode */
11383         { PR_4_UNATTACHED_INODE,
11384           "@u @i %i\n",
11385           PROMPT_CONNECT, 0 },
11386
11387         /* Inode ref count wrong */
11388         { PR_4_BAD_REF_COUNT,
11389           N_("@i %i ref count is %Il, @s %N.  "),
11390           PROMPT_FIX, PR_PREEN_OK },
11391
11392         { PR_4_INCONSISTENT_COUNT,
11393           N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
11394           "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
11395           "@i_link_info[%i] is %N, @i.i_links_count is %Il.  "
11396           "They should be the same!\n"),
11397           PROMPT_NONE, 0 },
11398
11399         /* Pass 5 errors */
11400
11401         /* Pass 5: Checking group summary information */
11402         { PR_5_PASS_HEADER,
11403           N_("Pass 5: Checking @g summary information\n"),
11404           PROMPT_NONE, 0 },
11405
11406         /* Padding at end of inode bitmap is not set. */
11407         { PR_5_INODE_BMAP_PADDING,
11408           N_("Padding at end of @i @B is not set. "),
11409           PROMPT_FIX, PR_PREEN_OK },
11410
11411         /* Padding at end of block bitmap is not set. */
11412         { PR_5_BLOCK_BMAP_PADDING,
11413           N_("Padding at end of @b @B is not set. "),
11414           PROMPT_FIX, PR_PREEN_OK },
11415
11416         /* Block bitmap differences header */
11417         { PR_5_BLOCK_BITMAP_HEADER,
11418           N_("@b @B differences: "),
11419           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
11420
11421         /* Block not used, but marked in bitmap */
11422         { PR_5_BLOCK_UNUSED,
11423           " -%b",
11424           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11425
11426         /* Block used, but not marked used in bitmap */
11427         { PR_5_BLOCK_USED,
11428           " +%b",
11429           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11430
11431         /* Block bitmap differences end */
11432         { PR_5_BLOCK_BITMAP_END,
11433           "\n",
11434           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11435
11436         /* Inode bitmap differences header */
11437         { PR_5_INODE_BITMAP_HEADER,
11438           N_("@i @B differences: "),
11439           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
11440
11441         /* Inode not used, but marked in bitmap */
11442         { PR_5_INODE_UNUSED,
11443           " -%i",
11444           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11445
11446         /* Inode used, but not marked used in bitmap */
11447         { PR_5_INODE_USED,
11448           " +%i",
11449           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11450
11451         /* Inode bitmap differences end */
11452         { PR_5_INODE_BITMAP_END,
11453           "\n",
11454           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11455
11456         /* Free inodes count for group wrong */
11457         { PR_5_FREE_INODE_COUNT_GROUP,
11458           N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
11459           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11460
11461         /* Directories count for group wrong */
11462         { PR_5_FREE_DIR_COUNT_GROUP,
11463           N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
11464           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11465
11466         /* Free inodes count wrong */
11467         { PR_5_FREE_INODE_COUNT,
11468           N_("Free @is count wrong (%i, counted=%j).\n"),
11469           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11470
11471         /* Free blocks count for group wrong */
11472         { PR_5_FREE_BLOCK_COUNT_GROUP,
11473           N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
11474           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11475
11476         /* Free blocks count wrong */
11477         { PR_5_FREE_BLOCK_COUNT,
11478           N_("Free @bs count wrong (%b, counted=%c).\n"),
11479           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11480
11481         /* Programming error: bitmap endpoints don't match */
11482         { PR_5_BMAP_ENDPOINTS,
11483           N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
11484           "match calculated @B endpoints (%i, %j)\n"),
11485           PROMPT_NONE, PR_FATAL },
11486
11487         /* Internal error: fudging end of bitmap */
11488         { PR_5_FUDGE_BITMAP_ERROR,
11489           N_("Internal error: fudging end of bitmap (%N)\n"),
11490           PROMPT_NONE, PR_FATAL },
11491
11492         /* Error copying in replacement inode bitmap */
11493         { PR_5_COPY_IBITMAP_ERROR,
11494           "Error copying in replacement @i @B: %m\n",
11495           PROMPT_NONE, PR_FATAL },
11496
11497         /* Error copying in replacement block bitmap */
11498         { PR_5_COPY_BBITMAP_ERROR,
11499           "Error copying in replacement @b @B: %m\n",
11500           PROMPT_NONE, PR_FATAL },
11501
11502         /* Block range not used, but marked in bitmap */
11503         { PR_5_BLOCK_RANGE_UNUSED,
11504           " -(%b--%c)",
11505           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11506
11507         /* Block range used, but not marked used in bitmap */
11508         { PR_5_BLOCK_RANGE_USED,
11509           " +(%b--%c)",
11510           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11511
11512         /* Inode range not used, but marked in bitmap */
11513         { PR_5_INODE_RANGE_UNUSED,
11514           " -(%i--%j)",
11515           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11516
11517         /* Inode range used, but not marked used in bitmap */
11518         { PR_5_INODE_RANGE_USED,
11519           " +(%i--%j)",
11520           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11521
11522         { 0 }
11523 };
11524
11525 /*
11526  * This is the latch flags register.  It allows several problems to be
11527  * "latched" together.  This means that the user has to answer but one
11528  * question for the set of problems, and all of the associated
11529  * problems will be either fixed or not fixed.
11530  */
11531 static struct latch_descr pr_latch_info[] = {
11532         { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
11533         { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
11534         { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
11535         { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
11536         { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
11537         { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
11538         { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
11539         { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
11540         { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
11541         { -1, 0, 0 },
11542 };
11543
11544 static const struct e2fsck_problem *find_problem(problem_t code)
11545 {
11546         int     i;
11547
11548         for (i=0; problem_table[i].e2p_code; i++) {
11549                 if (problem_table[i].e2p_code == code)
11550                         return &problem_table[i];
11551         }
11552         return 0;
11553 }
11554
11555 static struct latch_descr *find_latch(int code)
11556 {
11557         int     i;
11558
11559         for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
11560                 if (pr_latch_info[i].latch_code == code)
11561                         return &pr_latch_info[i];
11562         }
11563         return 0;
11564 }
11565
11566 int end_problem_latch(e2fsck_t ctx, int mask)
11567 {
11568         struct latch_descr *ldesc;
11569         struct problem_context pctx;
11570         int answer = -1;
11571
11572         ldesc = find_latch(mask);
11573         if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
11574                 clear_problem_context(&pctx);
11575                 answer = fix_problem(ctx, ldesc->end_message, &pctx);
11576         }
11577         ldesc->flags &= ~(PRL_VARIABLE);
11578         return answer;
11579 }
11580
11581 int set_latch_flags(int mask, int setflags, int clearflags)
11582 {
11583         struct latch_descr *ldesc;
11584
11585         ldesc = find_latch(mask);
11586         if (!ldesc)
11587                 return -1;
11588         ldesc->flags |= setflags;
11589         ldesc->flags &= ~clearflags;
11590         return 0;
11591 }
11592
11593 void clear_problem_context(struct problem_context *ctx)
11594 {
11595         memset(ctx, 0, sizeof(struct problem_context));
11596         ctx->blkcount = -1;
11597         ctx->group = -1;
11598 }
11599
11600 int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
11601 {
11602         ext2_filsys fs = ctx->fs;
11603         const struct e2fsck_problem *ptr;
11604         struct latch_descr *ldesc = 0;
11605         const char *message;
11606         int             def_yn, answer, ans;
11607         int             print_answer = 0;
11608         int             suppress = 0;
11609
11610         ptr = find_problem(code);
11611         if (!ptr) {
11612                 printf(_("Unhandled error code (0x%x)!\n"), code);
11613                 return 0;
11614         }
11615         def_yn = 1;
11616         if ((ptr->flags & PR_NO_DEFAULT) ||
11617             ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
11618             (ctx->options & E2F_OPT_NO))
11619                 def_yn= 0;
11620
11621         /*
11622          * Do special latch processing.  This is where we ask the
11623          * latch question, if it exists
11624          */
11625         if (ptr->flags & PR_LATCH_MASK) {
11626                 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
11627                 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
11628                         ans = fix_problem(ctx, ldesc->question, pctx);
11629                         if (ans == 1)
11630                                 ldesc->flags |= PRL_YES;
11631                         if (ans == 0)
11632                                 ldesc->flags |= PRL_NO;
11633                         ldesc->flags |= PRL_LATCHED;
11634                 }
11635                 if (ldesc->flags & PRL_SUPPRESS)
11636                         suppress++;
11637         }
11638         if ((ptr->flags & PR_PREEN_NOMSG) &&
11639             (ctx->options & E2F_OPT_PREEN))
11640                 suppress++;
11641         if ((ptr->flags & PR_NO_NOMSG) &&
11642             (ctx->options & E2F_OPT_NO))
11643                 suppress++;
11644         if (!suppress) {
11645                 message = ptr->e2p_description;
11646                 if ((ctx->options & E2F_OPT_PREEN) &&
11647                     !(ptr->flags & PR_PREEN_NOHDR)) {
11648                         printf("%s: ", ctx->device_name ?
11649                                ctx->device_name : ctx->filesystem_name);
11650                 }
11651                 if (*message)
11652                         print_e2fsck_message(ctx, _(message), pctx, 1);
11653         }
11654         if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
11655                 preenhalt(ctx);
11656
11657         if (ptr->flags & PR_FATAL)
11658                 fatal_error(ctx, 0);
11659
11660         if (ptr->prompt == PROMPT_NONE) {
11661                 if (ptr->flags & PR_NOCOLLATE)
11662                         answer = -1;
11663                 else
11664                         answer = def_yn;
11665         } else {
11666                 if (ctx->options & E2F_OPT_PREEN) {
11667                         answer = def_yn;
11668                         if (!(ptr->flags & PR_PREEN_NOMSG))
11669                                 print_answer = 1;
11670                 } else if ((ptr->flags & PR_LATCH_MASK) &&
11671                            (ldesc->flags & (PRL_YES | PRL_NO))) {
11672                         if (!suppress)
11673                                 print_answer = 1;
11674                         if (ldesc->flags & PRL_YES)
11675                                 answer = 1;
11676                         else
11677                                 answer = 0;
11678                 } else
11679                         answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
11680                 if (!answer && !(ptr->flags & PR_NO_OK))
11681                         ext2fs_unmark_valid(fs);
11682
11683                 if (print_answer)
11684                         printf("%s.\n", answer ?
11685                                _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
11686
11687         }
11688
11689         if ((ptr->prompt == PROMPT_ABORT) && answer)
11690                 fatal_error(ctx, 0);
11691
11692         if (ptr->flags & PR_AFTER_CODE)
11693                 answer = fix_problem(ctx, ptr->second_code, pctx);
11694
11695         return answer;
11696 }
11697
11698 /*
11699  * linux/fs/recovery.c
11700  *
11701  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
11702  */
11703
11704 /*
11705  * Maintain information about the progress of the recovery job, so that
11706  * the different passes can carry information between them.
11707  */
11708 struct recovery_info
11709 {
11710         tid_t           start_transaction;
11711         tid_t           end_transaction;
11712
11713         int             nr_replays;
11714         int             nr_revokes;
11715         int             nr_revoke_hits;
11716 };
11717
11718 enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
11719 static int do_one_pass(journal_t *journal,
11720                                 struct recovery_info *info, enum passtype pass);
11721 static int scan_revoke_records(journal_t *, struct buffer_head *,
11722                                 tid_t, struct recovery_info *);
11723
11724 /*
11725  * Read a block from the journal
11726  */
11727
11728 static int jread(struct buffer_head **bhp, journal_t *journal,
11729                  unsigned int offset)
11730 {
11731         int err;
11732         unsigned long blocknr;
11733         struct buffer_head *bh;
11734
11735         *bhp = NULL;
11736
11737         J_ASSERT (offset < journal->j_maxlen);
11738
11739         err = journal_bmap(journal, offset, &blocknr);
11740
11741         if (err) {
11742                 printk (KERN_ERR "JBD: bad block at offset %u\n",
11743                         offset);
11744                 return err;
11745         }
11746
11747         bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
11748         if (!bh)
11749                 return -ENOMEM;
11750
11751         if (!buffer_uptodate(bh)) {
11752                 /* If this is a brand new buffer, start readahead.
11753                    Otherwise, we assume we are already reading it.  */
11754                 if (!buffer_req(bh))
11755                         do_readahead(journal, offset);
11756                 wait_on_buffer(bh);
11757         }
11758
11759         if (!buffer_uptodate(bh)) {
11760                 printk (KERN_ERR "JBD: Failed to read block at offset %u\n",
11761                         offset);
11762                 brelse(bh);
11763                 return -EIO;
11764         }
11765
11766         *bhp = bh;
11767         return 0;
11768 }
11769
11770
11771 /*
11772  * Count the number of in-use tags in a journal descriptor block.
11773  */
11774
11775 static int count_tags(struct buffer_head *bh, int size)
11776 {
11777         char *                  tagp;
11778         journal_block_tag_t *   tag;
11779         int                     nr = 0;
11780
11781         tagp = &bh->b_data[sizeof(journal_header_t)];
11782
11783         while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
11784                 tag = (journal_block_tag_t *) tagp;
11785
11786                 nr++;
11787                 tagp += sizeof(journal_block_tag_t);
11788                 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
11789                         tagp += 16;
11790
11791                 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
11792                         break;
11793         }
11794
11795         return nr;
11796 }
11797
11798
11799 /* Make sure we wrap around the log correctly! */
11800 #define wrap(journal, var)                                              \
11801 do {                                                                    \
11802         if (var >= (journal)->j_last)                                   \
11803                 var -= ((journal)->j_last - (journal)->j_first);        \
11804 } while (0)
11805
11806 /**
11807  * int journal_recover(journal_t *journal) - recovers a on-disk journal
11808  * @journal: the journal to recover
11809  *
11810  * The primary function for recovering the log contents when mounting a
11811  * journaled device.
11812  *
11813  * Recovery is done in three passes.  In the first pass, we look for the
11814  * end of the log.  In the second, we assemble the list of revoke
11815  * blocks.  In the third and final pass, we replay any un-revoked blocks
11816  * in the log.
11817  */
11818 int journal_recover(journal_t *journal)
11819 {
11820         int                     err;
11821         journal_superblock_t *  sb;
11822
11823         struct recovery_info    info;
11824
11825         memset(&info, 0, sizeof(info));
11826         sb = journal->j_superblock;
11827
11828         /*
11829          * The journal superblock's s_start field (the current log head)
11830          * is always zero if, and only if, the journal was cleanly
11831          * unmounted.
11832          */
11833
11834         if (!sb->s_start) {
11835                 jbd_debug(1, "No recovery required, last transaction %d\n",
11836                           ntohl(sb->s_sequence));
11837                 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
11838                 return 0;
11839         }
11840
11841         err = do_one_pass(journal, &info, PASS_SCAN);
11842         if (!err)
11843                 err = do_one_pass(journal, &info, PASS_REVOKE);
11844         if (!err)
11845                 err = do_one_pass(journal, &info, PASS_REPLAY);
11846
11847         jbd_debug(0, "JBD: recovery, exit status %d, "
11848                   "recovered transactions %u to %u\n",
11849                   err, info.start_transaction, info.end_transaction);
11850         jbd_debug(0, "JBD: Replayed %d and revoked %d/%d blocks\n",
11851                   info.nr_replays, info.nr_revoke_hits, info.nr_revokes);
11852
11853         /* Restart the log at the next transaction ID, thus invalidating
11854          * any existing commit records in the log. */
11855         journal->j_transaction_sequence = ++info.end_transaction;
11856
11857         journal_clear_revoke(journal);
11858         sync_blockdev(journal->j_fs_dev);
11859         return err;
11860 }
11861
11862 static int do_one_pass(journal_t *journal,
11863                         struct recovery_info *info, enum passtype pass)
11864 {
11865         unsigned int            first_commit_ID, next_commit_ID;
11866         unsigned long           next_log_block;
11867         int                     err, success = 0;
11868         journal_superblock_t *  sb;
11869         journal_header_t *      tmp;
11870         struct buffer_head *    bh;
11871         unsigned int            sequence;
11872         int                     blocktype;
11873
11874         /* Precompute the maximum metadata descriptors in a descriptor block */
11875         int                     MAX_BLOCKS_PER_DESC;
11876         MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
11877                                / sizeof(journal_block_tag_t));
11878
11879         /*
11880          * First thing is to establish what we expect to find in the log
11881          * (in terms of transaction IDs), and where (in terms of log
11882          * block offsets): query the superblock.
11883          */
11884
11885         sb = journal->j_superblock;
11886         next_commit_ID = ntohl(sb->s_sequence);
11887         next_log_block = ntohl(sb->s_start);
11888
11889         first_commit_ID = next_commit_ID;
11890         if (pass == PASS_SCAN)
11891                 info->start_transaction = first_commit_ID;
11892
11893         jbd_debug(1, "Starting recovery pass %d\n", pass);
11894
11895         /*
11896          * Now we walk through the log, transaction by transaction,
11897          * making sure that each transaction has a commit block in the
11898          * expected place.  Each complete transaction gets replayed back
11899          * into the main filesystem.
11900          */
11901
11902         while (1) {
11903                 int                     flags;
11904                 char *                  tagp;
11905                 journal_block_tag_t *   tag;
11906                 struct buffer_head *    obh;
11907                 struct buffer_head *    nbh;
11908
11909                 /* If we already know where to stop the log traversal,
11910                  * check right now that we haven't gone past the end of
11911                  * the log. */
11912
11913                 if (pass != PASS_SCAN)
11914                         if (tid_geq(next_commit_ID, info->end_transaction))
11915                                 break;
11916
11917                 jbd_debug(2, "Scanning for sequence ID %u at %lu/%lu\n",
11918                           next_commit_ID, next_log_block, journal->j_last);
11919
11920                 /* Skip over each chunk of the transaction looking
11921                  * either the next descriptor block or the final commit
11922                  * record. */
11923
11924                 jbd_debug(3, "JBD: checking block %ld\n", next_log_block);
11925                 err = jread(&bh, journal, next_log_block);
11926                 if (err)
11927                         goto failed;
11928
11929                 next_log_block++;
11930                 wrap(journal, next_log_block);
11931
11932                 /* What kind of buffer is it?
11933                  *
11934                  * If it is a descriptor block, check that it has the
11935                  * expected sequence number.  Otherwise, we're all done
11936                  * here. */
11937
11938                 tmp = (journal_header_t *)bh->b_data;
11939
11940                 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
11941                         brelse(bh);
11942                         break;
11943                 }
11944
11945                 blocktype = ntohl(tmp->h_blocktype);
11946                 sequence = ntohl(tmp->h_sequence);
11947                 jbd_debug(3, "Found magic %d, sequence %d\n",
11948                           blocktype, sequence);
11949
11950                 if (sequence != next_commit_ID) {
11951                         brelse(bh);
11952                         break;
11953                 }
11954
11955                 /* OK, we have a valid descriptor block which matches
11956                  * all of the sequence number checks.  What are we going
11957                  * to do with it?  That depends on the pass... */
11958
11959                 switch(blocktype) {
11960                 case JFS_DESCRIPTOR_BLOCK:
11961                         /* If it is a valid descriptor block, replay it
11962                          * in pass REPLAY; otherwise, just skip over the
11963                          * blocks it describes. */
11964                         if (pass != PASS_REPLAY) {
11965                                 next_log_block +=
11966                                         count_tags(bh, journal->j_blocksize);
11967                                 wrap(journal, next_log_block);
11968                                 brelse(bh);
11969                                 continue;
11970                         }
11971
11972                         /* A descriptor block: we can now write all of
11973                          * the data blocks.  Yay, useful work is finally
11974                          * getting done here! */
11975
11976                         tagp = &bh->b_data[sizeof(journal_header_t)];
11977                         while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
11978                                <= journal->j_blocksize) {
11979                                 unsigned long io_block;
11980
11981                                 tag = (journal_block_tag_t *) tagp;
11982                                 flags = ntohl(tag->t_flags);
11983
11984                                 io_block = next_log_block++;
11985                                 wrap(journal, next_log_block);
11986                                 err = jread(&obh, journal, io_block);
11987                                 if (err) {
11988                                         /* Recover what we can, but
11989                                          * report failure at the end. */
11990                                         success = err;
11991                                         printk (KERN_ERR
11992                                                 "JBD: IO error %d recovering "
11993                                                 "block %ld in log\n",
11994                                                 err, io_block);
11995                                 } else {
11996                                         unsigned long blocknr;
11997
11998                                         J_ASSERT(obh != NULL);
11999                                         blocknr = ntohl(tag->t_blocknr);
12000
12001                                         /* If the block has been
12002                                          * revoked, then we're all done
12003                                          * here. */
12004                                         if (journal_test_revoke
12005                                             (journal, blocknr,
12006                                              next_commit_ID)) {
12007                                                 brelse(obh);
12008                                                 ++info->nr_revoke_hits;
12009                                                 goto skip_write;
12010                                         }
12011
12012                                         /* Find a buffer for the new
12013                                          * data being restored */
12014                                         nbh = getblk(journal->j_fs_dev,
12015                                                        blocknr,
12016                                                      journal->j_blocksize);
12017                                         if (nbh == NULL) {
12018                                                 printk(KERN_ERR
12019                                                        "JBD: Out of memory "
12020                                                        "during recovery.\n");
12021                                                 err = -ENOMEM;
12022                                                 brelse(bh);
12023                                                 brelse(obh);
12024                                                 goto failed;
12025                                         }
12026
12027                                         lock_buffer(nbh);
12028                                         memcpy(nbh->b_data, obh->b_data,
12029                                                         journal->j_blocksize);
12030                                         if (flags & JFS_FLAG_ESCAPE) {
12031                                                 *((unsigned int *)bh->b_data) =
12032                                                         htonl(JFS_MAGIC_NUMBER);
12033                                         }
12034
12035                                         BUFFER_TRACE(nbh, "marking dirty");
12036                                         mark_buffer_uptodate(nbh, 1);
12037                                         mark_buffer_dirty(nbh);
12038                                         BUFFER_TRACE(nbh, "marking uptodate");
12039                                         ++info->nr_replays;
12040                                         /* ll_rw_block(WRITE, 1, &nbh); */
12041                                         unlock_buffer(nbh);
12042                                         brelse(obh);
12043                                         brelse(nbh);
12044                                 }
12045
12046                         skip_write:
12047                                 tagp += sizeof(journal_block_tag_t);
12048                                 if (!(flags & JFS_FLAG_SAME_UUID))
12049                                         tagp += 16;
12050
12051                                 if (flags & JFS_FLAG_LAST_TAG)
12052                                         break;
12053                         }
12054
12055                         brelse(bh);
12056                         continue;
12057
12058                 case JFS_COMMIT_BLOCK:
12059                         /* Found an expected commit block: not much to
12060                          * do other than move on to the next sequence
12061                          * number. */
12062                         brelse(bh);
12063                         next_commit_ID++;
12064                         continue;
12065
12066                 case JFS_REVOKE_BLOCK:
12067                         /* If we aren't in the REVOKE pass, then we can
12068                          * just skip over this block. */
12069                         if (pass != PASS_REVOKE) {
12070                                 brelse(bh);
12071                                 continue;
12072                         }
12073
12074                         err = scan_revoke_records(journal, bh,
12075                                                   next_commit_ID, info);
12076                         brelse(bh);
12077                         if (err)
12078                                 goto failed;
12079                         continue;
12080
12081                 default:
12082                         jbd_debug(3, "Unrecognised magic %d, end of scan.\n",
12083                                   blocktype);
12084                         goto done;
12085                 }
12086         }
12087
12088  done:
12089         /*
12090          * We broke out of the log scan loop: either we came to the
12091          * known end of the log or we found an unexpected block in the
12092          * log.  If the latter happened, then we know that the "current"
12093          * transaction marks the end of the valid log.
12094          */
12095
12096         if (pass == PASS_SCAN)
12097                 info->end_transaction = next_commit_ID;
12098         else {
12099                 /* It's really bad news if different passes end up at
12100                  * different places (but possible due to IO errors). */
12101                 if (info->end_transaction != next_commit_ID) {
12102                         printk (KERN_ERR "JBD: recovery pass %d ended at "
12103                                 "transaction %u, expected %u\n",
12104                                 pass, next_commit_ID, info->end_transaction);
12105                         if (!success)
12106                                 success = -EIO;
12107                 }
12108         }
12109
12110         return success;
12111
12112  failed:
12113         return err;
12114 }
12115
12116
12117 /* Scan a revoke record, marking all blocks mentioned as revoked. */
12118
12119 static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
12120                                tid_t sequence, struct recovery_info *info)
12121 {
12122         journal_revoke_header_t *header;
12123         int offset, max;
12124
12125         header = (journal_revoke_header_t *) bh->b_data;
12126         offset = sizeof(journal_revoke_header_t);
12127         max = ntohl(header->r_count);
12128
12129         while (offset < max) {
12130                 unsigned long blocknr;
12131                 int err;
12132
12133                 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
12134                 offset += 4;
12135                 err = journal_set_revoke(journal, blocknr, sequence);
12136                 if (err)
12137                         return err;
12138                 ++info->nr_revokes;
12139         }
12140         return 0;
12141 }
12142
12143
12144 /*
12145  * rehash.c --- rebuild hash tree directories
12146  *
12147  * This algorithm is designed for simplicity of implementation and to
12148  * pack the directory as much as possible.  It however requires twice
12149  * as much memory as the size of the directory.  The maximum size
12150  * directory supported using a 4k blocksize is roughly a gigabyte, and
12151  * so there may very well be problems with machines that don't have
12152  * virtual memory, and obscenely large directories.
12153  *
12154  * An alternate algorithm which is much more disk intensive could be
12155  * written, and probably will need to be written in the future.  The
12156  * design goals of such an algorithm are: (a) use (roughly) constant
12157  * amounts of memory, no matter how large the directory, (b) the
12158  * directory must be safe at all times, even if e2fsck is interrupted
12159  * in the middle, (c) we must use minimal amounts of extra disk
12160  * blocks.  This pretty much requires an incremental approach, where
12161  * we are reading from one part of the directory, and inserting into
12162  * the front half.  So the algorithm will have to keep track of a
12163  * moving block boundary between the new tree and the old tree, and
12164  * files will need to be moved from the old directory and inserted
12165  * into the new tree.  If the new directory requires space which isn't
12166  * yet available, blocks from the beginning part of the old directory
12167  * may need to be moved to the end of the directory to make room for
12168  * the new tree:
12169  *
12170  *    --------------------------------------------------------
12171  *    |  new tree   |        | old tree                      |
12172  *    --------------------------------------------------------
12173  *                  ^ ptr    ^ptr
12174  *                tail new   head old
12175  *
12176  * This is going to be a pain in the tuckus to implement, and will
12177  * require a lot more disk accesses.  So I'm going to skip it for now;
12178  * it's only really going to be an issue for really, really big
12179  * filesystems (when we reach the level of tens of millions of files
12180  * in a single directory).  It will probably be easier to simply
12181  * require that e2fsck use VM first.
12182  */
12183
12184 struct fill_dir_struct {
12185         char *buf;
12186         struct ext2_inode *inode;
12187         int err;
12188         e2fsck_t ctx;
12189         struct hash_entry *harray;
12190         int max_array, num_array;
12191         int dir_size;
12192         int compress;
12193         ino_t parent;
12194 };
12195
12196 struct hash_entry {
12197         ext2_dirhash_t  hash;
12198         ext2_dirhash_t  minor_hash;
12199         struct ext2_dir_entry   *dir;
12200 };
12201
12202 struct out_dir {
12203         int             num;
12204         int             max;
12205         char            *buf;
12206         ext2_dirhash_t  *hashes;
12207 };
12208
12209 static int fill_dir_block(ext2_filsys fs,
12210                           blk_t *block_nr,
12211                           e2_blkcnt_t blockcnt,
12212                           blk_t ref_block FSCK_ATTR((unused)),
12213                           int ref_offset FSCK_ATTR((unused)),
12214                           void *priv_data)
12215 {
12216         struct fill_dir_struct  *fd = (struct fill_dir_struct *) priv_data;
12217         struct hash_entry       *new_array, *ent;
12218         struct ext2_dir_entry   *dirent;
12219         char                    *dir;
12220         unsigned int            offset, dir_offset;
12221
12222         if (blockcnt < 0)
12223                 return 0;
12224
12225         offset = blockcnt * fs->blocksize;
12226         if (offset + fs->blocksize > fd->inode->i_size) {
12227                 fd->err = EXT2_ET_DIR_CORRUPTED;
12228                 return BLOCK_ABORT;
12229         }
12230         dir = (fd->buf+offset);
12231         if (HOLE_BLKADDR(*block_nr)) {
12232                 memset(dir, 0, fs->blocksize);
12233                 dirent = (struct ext2_dir_entry *) dir;
12234                 dirent->rec_len = fs->blocksize;
12235         } else {
12236                 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
12237                 if (fd->err)
12238                         return BLOCK_ABORT;
12239         }
12240         /* While the directory block is "hot", index it. */
12241         dir_offset = 0;
12242         while (dir_offset < fs->blocksize) {
12243                 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
12244                 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
12245                     (dirent->rec_len < 8) ||
12246                     ((dirent->rec_len % 4) != 0) ||
12247                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
12248                         fd->err = EXT2_ET_DIR_CORRUPTED;
12249                         return BLOCK_ABORT;
12250                 }
12251                 dir_offset += dirent->rec_len;
12252                 if (dirent->inode == 0)
12253                         continue;
12254                 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
12255                     (dirent->name[0] == '.'))
12256                         continue;
12257                 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
12258                     (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
12259                         fd->parent = dirent->inode;
12260                         continue;
12261                 }
12262                 if (fd->num_array >= fd->max_array) {
12263                         new_array = realloc(fd->harray,
12264                             sizeof(struct hash_entry) * (fd->max_array+500));
12265                         if (!new_array) {
12266                                 fd->err = ENOMEM;
12267                                 return BLOCK_ABORT;
12268                         }
12269                         fd->harray = new_array;
12270                         fd->max_array += 500;
12271                 }
12272                 ent = fd->harray + fd->num_array++;
12273                 ent->dir = dirent;
12274                 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
12275                 if (fd->compress)
12276                         ent->hash = ent->minor_hash = 0;
12277                 else {
12278                         fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
12279                                                  dirent->name,
12280                                                  dirent->name_len & 0xFF,
12281                                                  fs->super->s_hash_seed,
12282                                                  &ent->hash, &ent->minor_hash);
12283                         if (fd->err)
12284                                 return BLOCK_ABORT;
12285                 }
12286         }
12287
12288         return 0;
12289 }
12290
12291 /* Used for sorting the hash entry */
12292 static EXT2_QSORT_TYPE name_cmp(const void *a, const void *b)
12293 {
12294         const struct hash_entry *he_a = (const struct hash_entry *) a;
12295         const struct hash_entry *he_b = (const struct hash_entry *) b;
12296         int     ret;
12297         int     min_len;
12298
12299         min_len = he_a->dir->name_len;
12300         if (min_len > he_b->dir->name_len)
12301                 min_len = he_b->dir->name_len;
12302
12303         ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
12304         if (ret == 0) {
12305                 if (he_a->dir->name_len > he_b->dir->name_len)
12306                         ret = 1;
12307                 else if (he_a->dir->name_len < he_b->dir->name_len)
12308                         ret = -1;
12309                 else
12310                         ret = he_b->dir->inode - he_a->dir->inode;
12311         }
12312         return ret;
12313 }
12314
12315 /* Used for sorting the hash entry */
12316 static EXT2_QSORT_TYPE hash_cmp(const void *a, const void *b)
12317 {
12318         const struct hash_entry *he_a = (const struct hash_entry *) a;
12319         const struct hash_entry *he_b = (const struct hash_entry *) b;
12320         int     ret;
12321
12322         if (he_a->hash > he_b->hash)
12323                 ret = 1;
12324         else if (he_a->hash < he_b->hash)
12325                 ret = -1;
12326         else {
12327                 if (he_a->minor_hash > he_b->minor_hash)
12328                         ret = 1;
12329                 else if (he_a->minor_hash < he_b->minor_hash)
12330                         ret = -1;
12331                 else
12332                         ret = name_cmp(a, b);
12333         }
12334         return ret;
12335 }
12336
12337 static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
12338                                 int blocks)
12339 {
12340         void                    *new_mem;
12341
12342         if (outdir->max) {
12343                 new_mem = realloc(outdir->buf, blocks * fs->blocksize);
12344                 if (!new_mem)
12345                         return ENOMEM;
12346                 outdir->buf = new_mem;
12347                 new_mem = realloc(outdir->hashes,
12348                                   blocks * sizeof(ext2_dirhash_t));
12349                 if (!new_mem)
12350                         return ENOMEM;
12351                 outdir->hashes = new_mem;
12352         } else {
12353                 outdir->buf = malloc(blocks * fs->blocksize);
12354                 outdir->hashes = malloc(blocks * sizeof(ext2_dirhash_t));
12355                 outdir->num = 0;
12356         }
12357         outdir->max = blocks;
12358         return 0;
12359 }
12360
12361 static void free_out_dir(struct out_dir *outdir)
12362 {
12363         if (outdir->buf)
12364                 free(outdir->buf);
12365         if (outdir->hashes)
12366                 free(outdir->hashes);
12367         outdir->max = 0;
12368         outdir->num =0;
12369 }
12370
12371 static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
12372                          char ** ret)
12373 {
12374         errcode_t       retval;
12375
12376         if (outdir->num >= outdir->max) {
12377                 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
12378                 if (retval)
12379                         return retval;
12380         }
12381         *ret = outdir->buf + (outdir->num++ * fs->blocksize);
12382         memset(*ret, 0, fs->blocksize);
12383         return 0;
12384 }
12385
12386 /*
12387  * This function is used to make a unique filename.  We do this by
12388  * appending ~0, and then incrementing the number.  However, we cannot
12389  * expand the length of the filename beyond the padding available in
12390  * the directory entry.
12391  */
12392 static void mutate_name(char *str, __u16 *len)
12393 {
12394         int     i;
12395         __u16   l = *len & 0xFF, h = *len & 0xff00;
12396
12397         /*
12398          * First check to see if it looks the name has been mutated
12399          * already
12400          */
12401         for (i = l-1; i > 0; i--) {
12402                 if (!isdigit(str[i]))
12403                         break;
12404         }
12405         if ((i == l-1) || (str[i] != '~')) {
12406                 if (((l-1) & 3) < 2)
12407                         l += 2;
12408                 else
12409                         l = (l+3) & ~3;
12410                 str[l-2] = '~';
12411                 str[l-1] = '0';
12412                 *len = l | h;
12413                 return;
12414         }
12415         for (i = l-1; i >= 0; i--) {
12416                 if (isdigit(str[i])) {
12417                         if (str[i] == '9')
12418                                 str[i] = '0';
12419                         else {
12420                                 str[i]++;
12421                                 return;
12422                         }
12423                         continue;
12424                 }
12425                 if (i == 1) {
12426                         if (str[0] == 'z')
12427                                 str[0] = 'A';
12428                         else if (str[0] == 'Z') {
12429                                 str[0] = '~';
12430                                 str[1] = '0';
12431                         } else
12432                                 str[0]++;
12433                 } else if (i > 0) {
12434                         str[i] = '1';
12435                         str[i-1] = '~';
12436                 } else {
12437                         if (str[0] == '~')
12438                                 str[0] = 'a';
12439                         else
12440                                 str[0]++;
12441                 }
12442                 break;
12443         }
12444 }
12445
12446 static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
12447                                     ext2_ino_t ino,
12448                                     struct fill_dir_struct *fd)
12449 {
12450         struct problem_context  pctx;
12451         struct hash_entry       *ent, *prev;
12452         int                     i, j;
12453         int                     fixed = 0;
12454         char                    new_name[256];
12455         __u16                   new_len;
12456
12457         clear_problem_context(&pctx);
12458         pctx.ino = ino;
12459
12460         for (i=1; i < fd->num_array; i++) {
12461                 ent = fd->harray + i;
12462                 prev = ent - 1;
12463                 if (!ent->dir->inode ||
12464                     ((ent->dir->name_len & 0xFF) !=
12465                      (prev->dir->name_len & 0xFF)) ||
12466                     (strncmp(ent->dir->name, prev->dir->name,
12467                              ent->dir->name_len & 0xFF)))
12468                         continue;
12469                 pctx.dirent = ent->dir;
12470                 if ((ent->dir->inode == prev->dir->inode) &&
12471                     fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
12472                         e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
12473                         ent->dir->inode = 0;
12474                         fixed++;
12475                         continue;
12476                 }
12477                 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
12478                 new_len = ent->dir->name_len;
12479                 mutate_name(new_name, &new_len);
12480                 for (j=0; j < fd->num_array; j++) {
12481                         if ((i==j) ||
12482                             ((ent->dir->name_len & 0xFF) !=
12483                              (fd->harray[j].dir->name_len & 0xFF)) ||
12484                             (strncmp(new_name, fd->harray[j].dir->name,
12485                                      new_len & 0xFF)))
12486                                 continue;
12487                         mutate_name(new_name, &new_len);
12488
12489                         j = -1;
12490                 }
12491                 new_name[new_len & 0xFF] = 0;
12492                 pctx.str = new_name;
12493                 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
12494                         memcpy(ent->dir->name, new_name, new_len & 0xFF);
12495                         ent->dir->name_len = new_len;
12496                         ext2fs_dirhash(fs->super->s_def_hash_version,
12497                                        ent->dir->name,
12498                                        ent->dir->name_len & 0xFF,
12499                                        fs->super->s_hash_seed,
12500                                        &ent->hash, &ent->minor_hash);
12501                         fixed++;
12502                 }
12503         }
12504         return fixed;
12505 }
12506
12507
12508 static errcode_t copy_dir_entries(ext2_filsys fs,
12509                                   struct fill_dir_struct *fd,
12510                                   struct out_dir *outdir)
12511 {
12512         errcode_t               retval;
12513         char                    *block_start;
12514         struct hash_entry       *ent;
12515         struct ext2_dir_entry   *dirent;
12516         int                     i, rec_len, left;
12517         ext2_dirhash_t          prev_hash;
12518         int                     offset;
12519
12520         outdir->max = 0;
12521         retval = alloc_size_dir(fs, outdir,
12522                                 (fd->dir_size / fs->blocksize) + 2);
12523         if (retval)
12524                 return retval;
12525         outdir->num = fd->compress ? 0 : 1;
12526         offset = 0;
12527         outdir->hashes[0] = 0;
12528         prev_hash = 1;
12529         if ((retval = get_next_block(fs, outdir, &block_start)))
12530                 return retval;
12531         dirent = (struct ext2_dir_entry *) block_start;
12532         left = fs->blocksize;
12533         for (i=0; i < fd->num_array; i++) {
12534                 ent = fd->harray + i;
12535                 if (ent->dir->inode == 0)
12536                         continue;
12537                 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
12538                 if (rec_len > left) {
12539                         if (left)
12540                                 dirent->rec_len += left;
12541                         if ((retval = get_next_block(fs, outdir,
12542                                                       &block_start)))
12543                                 return retval;
12544                         offset = 0;
12545                 }
12546                 left = fs->blocksize - offset;
12547                 dirent = (struct ext2_dir_entry *) (block_start + offset);
12548                 if (offset == 0) {
12549                         if (ent->hash == prev_hash)
12550                                 outdir->hashes[outdir->num-1] = ent->hash | 1;
12551                         else
12552                                 outdir->hashes[outdir->num-1] = ent->hash;
12553                 }
12554                 dirent->inode = ent->dir->inode;
12555                 dirent->name_len = ent->dir->name_len;
12556                 dirent->rec_len = rec_len;
12557                 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
12558                 offset += rec_len;
12559                 left -= rec_len;
12560                 if (left < 12) {
12561                         dirent->rec_len += left;
12562                         offset += left;
12563                         left = 0;
12564                 }
12565                 prev_hash = ent->hash;
12566         }
12567         if (left)
12568                 dirent->rec_len += left;
12569
12570         return 0;
12571 }
12572
12573
12574 static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
12575                                     ext2_ino_t ino, ext2_ino_t parent)
12576 {
12577         struct ext2_dir_entry           *dir;
12578         struct ext2_dx_root_info        *root;
12579         struct ext2_dx_countlimit       *limits;
12580         int                             filetype = 0;
12581
12582         if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
12583                 filetype = EXT2_FT_DIR << 8;
12584
12585         memset(buf, 0, fs->blocksize);
12586         dir = (struct ext2_dir_entry *) buf;
12587         dir->inode = ino;
12588         dir->name[0] = '.';
12589         dir->name_len = 1 | filetype;
12590         dir->rec_len = 12;
12591         dir = (struct ext2_dir_entry *) (buf + 12);
12592         dir->inode = parent;
12593         dir->name[0] = '.';
12594         dir->name[1] = '.';
12595         dir->name_len = 2 | filetype;
12596         dir->rec_len = fs->blocksize - 12;
12597
12598         root = (struct ext2_dx_root_info *) (buf+24);
12599         root->reserved_zero = 0;
12600         root->hash_version = fs->super->s_def_hash_version;
12601         root->info_length = 8;
12602         root->indirect_levels = 0;
12603         root->unused_flags = 0;
12604
12605         limits = (struct ext2_dx_countlimit *) (buf+32);
12606         limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
12607         limits->count = 0;
12608
12609         return root;
12610 }
12611
12612
12613 static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
12614 {
12615         struct ext2_dir_entry           *dir;
12616         struct ext2_dx_countlimit       *limits;
12617
12618         memset(buf, 0, fs->blocksize);
12619         dir = (struct ext2_dir_entry *) buf;
12620         dir->inode = 0;
12621         dir->rec_len = fs->blocksize;
12622
12623         limits = (struct ext2_dx_countlimit *) (buf+8);
12624         limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
12625         limits->count = 0;
12626
12627         return (struct ext2_dx_entry *) limits;
12628 }
12629
12630 /*
12631  * This function takes the leaf nodes which have been written in
12632  * outdir, and populates the root node and any necessary interior nodes.
12633  */
12634 static errcode_t calculate_tree(ext2_filsys fs,
12635                                 struct out_dir *outdir,
12636                                 ext2_ino_t ino,
12637                                 ext2_ino_t parent)
12638 {
12639         struct ext2_dx_root_info        *root_info;
12640         struct ext2_dx_entry            *root, *dx_ent = 0;
12641         struct ext2_dx_countlimit       *root_limit, *limit;
12642         errcode_t                       retval;
12643         char                            * block_start;
12644         int                             i, c1, c2, nblks;
12645         int                             limit_offset, root_offset;
12646
12647         root_info = set_root_node(fs, outdir->buf, ino, parent);
12648         root_offset = limit_offset = ((char *) root_info - outdir->buf) +
12649                 root_info->info_length;
12650         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
12651         c1 = root_limit->limit;
12652         nblks = outdir->num;
12653
12654         /* Write out the pointer blocks */
12655         if (nblks-1 <= c1) {
12656                 /* Just write out the root block, and we're done */
12657                 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
12658                 for (i=1; i < nblks; i++) {
12659                         root->block = ext2fs_cpu_to_le32(i);
12660                         if (i != 1)
12661                                 root->hash =
12662                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
12663                         root++;
12664                         c1--;
12665                 }
12666         } else {
12667                 c2 = 0;
12668                 limit = 0;
12669                 root_info->indirect_levels = 1;
12670                 for (i=1; i < nblks; i++) {
12671                         if (c1 == 0)
12672                                 return ENOSPC;
12673                         if (c2 == 0) {
12674                                 if (limit)
12675                                         limit->limit = limit->count =
12676                 ext2fs_cpu_to_le16(limit->limit);
12677                                 root = (struct ext2_dx_entry *)
12678                                         (outdir->buf + root_offset);
12679                                 root->block = ext2fs_cpu_to_le32(outdir->num);
12680                                 if (i != 1)
12681                                         root->hash =
12682                         ext2fs_cpu_to_le32(outdir->hashes[i]);
12683                                 if ((retval =  get_next_block(fs, outdir,
12684                                                               &block_start)))
12685                                         return retval;
12686                                 dx_ent = set_int_node(fs, block_start);
12687                                 limit = (struct ext2_dx_countlimit *) dx_ent;
12688                                 c2 = limit->limit;
12689                                 root_offset += sizeof(struct ext2_dx_entry);
12690                                 c1--;
12691                         }
12692                         dx_ent->block = ext2fs_cpu_to_le32(i);
12693                         if (c2 != limit->limit)
12694                                 dx_ent->hash =
12695                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
12696                         dx_ent++;
12697                         c2--;
12698                 }
12699                 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
12700                 limit->limit = ext2fs_cpu_to_le16(limit->limit);
12701         }
12702         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
12703         root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
12704         root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
12705
12706         return 0;
12707 }
12708
12709 struct write_dir_struct {
12710         struct out_dir *outdir;
12711         errcode_t       err;
12712         e2fsck_t        ctx;
12713         int             cleared;
12714 };
12715
12716 /*
12717  * Helper function which writes out a directory block.
12718  */
12719 static int write_dir_block(ext2_filsys fs,
12720                            blk_t        *block_nr,
12721                            e2_blkcnt_t blockcnt,
12722                            blk_t ref_block FSCK_ATTR((unused)),
12723                            int ref_offset FSCK_ATTR((unused)),
12724                            void *priv_data)
12725 {
12726         struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
12727         blk_t   blk;
12728         char    *dir;
12729
12730         if (*block_nr == 0)
12731                 return 0;
12732         if (blockcnt >= wd->outdir->num) {
12733                 e2fsck_read_bitmaps(wd->ctx);
12734                 blk = *block_nr;
12735                 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
12736                 ext2fs_block_alloc_stats(fs, blk, -1);
12737                 *block_nr = 0;
12738                 wd->cleared++;
12739                 return BLOCK_CHANGED;
12740         }
12741         if (blockcnt < 0)
12742                 return 0;
12743
12744         dir = wd->outdir->buf + (blockcnt * fs->blocksize);
12745         wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
12746         if (wd->err)
12747                 return BLOCK_ABORT;
12748         return 0;
12749 }
12750
12751 static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
12752                                  struct out_dir *outdir,
12753                                  ext2_ino_t ino, int compress)
12754 {
12755         struct write_dir_struct wd;
12756         errcode_t       retval;
12757         struct ext2_inode       inode;
12758
12759         retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
12760         if (retval)
12761                 return retval;
12762
12763         wd.outdir = outdir;
12764         wd.err = 0;
12765         wd.ctx = ctx;
12766         wd.cleared = 0;
12767
12768         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
12769                                        write_dir_block, &wd);
12770         if (retval)
12771                 return retval;
12772         if (wd.err)
12773                 return wd.err;
12774
12775         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
12776         if (compress)
12777                 inode.i_flags &= ~EXT2_INDEX_FL;
12778         else
12779                 inode.i_flags |= EXT2_INDEX_FL;
12780         inode.i_size = outdir->num * fs->blocksize;
12781         inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
12782         e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
12783
12784         return 0;
12785 }
12786
12787 static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
12788 {
12789         ext2_filsys             fs = ctx->fs;
12790         errcode_t               retval;
12791         struct ext2_inode       inode;
12792         char                    *dir_buf = 0;
12793         struct fill_dir_struct  fd;
12794         struct out_dir          outdir;
12795
12796         outdir.max = outdir.num = 0;
12797         outdir.buf = 0;
12798         outdir.hashes = 0;
12799         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
12800
12801         retval = ENOMEM;
12802         fd.harray = 0;
12803         dir_buf = malloc(inode.i_size);
12804         if (!dir_buf)
12805                 goto errout;
12806
12807         fd.max_array = inode.i_size / 32;
12808         fd.num_array = 0;
12809         fd.harray = malloc(fd.max_array * sizeof(struct hash_entry));
12810         if (!fd.harray)
12811                 goto errout;
12812
12813         fd.ctx = ctx;
12814         fd.buf = dir_buf;
12815         fd.inode = &inode;
12816         fd.err = 0;
12817         fd.dir_size = 0;
12818         fd.compress = 0;
12819         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
12820             (inode.i_size / fs->blocksize) < 2)
12821                 fd.compress = 1;
12822         fd.parent = 0;
12823
12824         /* Read in the entire directory into memory */
12825         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
12826                                        fill_dir_block, &fd);
12827         if (fd.err) {
12828                 retval = fd.err;
12829                 goto errout;
12830         }
12831
12832 #if 0
12833         printf("%d entries (%d bytes) found in inode %d\n",
12834                fd.num_array, fd.dir_size, ino);
12835 #endif
12836
12837         /* Sort the list */
12838 resort:
12839         if (fd.compress)
12840                 qsort(fd.harray+2, fd.num_array-2,
12841                       sizeof(struct hash_entry), name_cmp);
12842         else
12843                 qsort(fd.harray, fd.num_array,
12844                       sizeof(struct hash_entry), hash_cmp);
12845
12846         /*
12847          * Look for duplicates
12848          */
12849         if (duplicate_search_and_fix(ctx, fs, ino, &fd))
12850                 goto resort;
12851
12852         if (ctx->options & E2F_OPT_NO) {
12853                 retval = 0;
12854                 goto errout;
12855         }
12856
12857         /*
12858          * Copy the directory entries.  In a htree directory these
12859          * will become the leaf nodes.
12860          */
12861         retval = copy_dir_entries(fs, &fd, &outdir);
12862         if (retval)
12863                 goto errout;
12864
12865         free(dir_buf); dir_buf = 0;
12866
12867         if (!fd.compress) {
12868                 /* Calculate the interior nodes */
12869                 retval = calculate_tree(fs, &outdir, ino, fd.parent);
12870                 if (retval)
12871                         goto errout;
12872         }
12873
12874         retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
12875         if (retval)
12876                 goto errout;
12877
12878 errout:
12879         if (dir_buf)
12880                 free(dir_buf);
12881         if (fd.harray)
12882                 free(fd.harray);
12883
12884         free_out_dir(&outdir);
12885         return retval;
12886 }
12887
12888 void e2fsck_rehash_directories(e2fsck_t ctx)
12889 {
12890         struct problem_context  pctx;
12891 #ifdef RESOURCE_TRACK
12892         struct resource_track   rtrack;
12893 #endif
12894         struct dir_info         *dir;
12895         ext2_u32_iterate        iter;
12896         ext2_ino_t              ino;
12897         errcode_t               retval;
12898         int                     i, cur, max, all_dirs, dir_index, first = 1;
12899
12900 #ifdef RESOURCE_TRACK
12901         init_resource_track(&rtrack);
12902 #endif
12903
12904         all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
12905
12906         if (!ctx->dirs_to_hash && !all_dirs)
12907                 return;
12908
12909         e2fsck_get_lost_and_found(ctx, 0);
12910
12911         clear_problem_context(&pctx);
12912
12913         dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
12914         cur = 0;
12915         if (all_dirs) {
12916                 i = 0;
12917                 max = e2fsck_get_num_dirinfo(ctx);
12918         } else {
12919                 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
12920                                                        &iter);
12921                 if (retval) {
12922                         pctx.errcode = retval;
12923                         fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
12924                         return;
12925                 }
12926                 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
12927         }
12928         while (1) {
12929                 if (all_dirs) {
12930                         if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
12931                                 break;
12932                         ino = dir->ino;
12933                 } else {
12934                         if (!ext2fs_u32_list_iterate(iter, &ino))
12935                                 break;
12936                 }
12937                 if (ino == ctx->lost_and_found)
12938                         continue;
12939                 pctx.dir = ino;
12940                 if (first) {
12941                         fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
12942                         first = 0;
12943                 }
12944 #if 0
12945                 fix_problem(ctx, PR_3A_OPTIMIZE_DIR, &pctx);
12946 #endif
12947                 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
12948                 if (pctx.errcode) {
12949                         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
12950                         fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
12951                 }
12952                 if (ctx->progress && !ctx->progress_fd)
12953                         e2fsck_simple_progress(ctx, "Rebuilding directory",
12954                                100.0 * (float) (++cur) / (float) max, ino);
12955         }
12956         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
12957         if (!all_dirs)
12958                 ext2fs_u32_list_iterate_end(iter);
12959
12960         if (ctx->dirs_to_hash)
12961                 ext2fs_u32_list_free(ctx->dirs_to_hash);
12962         ctx->dirs_to_hash = 0;
12963
12964 #ifdef RESOURCE_TRACK
12965         if (ctx->options & E2F_OPT_TIME2) {
12966                 e2fsck_clear_progbar(ctx);
12967                 print_resource_track("Pass 3A", &rtrack);
12968         }
12969 #endif
12970 }
12971
12972 /*
12973  * linux/fs/revoke.c
12974  *
12975  * Journal revoke routines for the generic filesystem journaling code;
12976  * part of the ext2fs journaling system.
12977  *
12978  * Revoke is the mechanism used to prevent old log records for deleted
12979  * metadata from being replayed on top of newer data using the same
12980  * blocks.  The revoke mechanism is used in two separate places:
12981  *
12982  * + Commit: during commit we write the entire list of the current
12983  *   transaction's revoked blocks to the journal
12984  *
12985  * + Recovery: during recovery we record the transaction ID of all
12986  *   revoked blocks.  If there are multiple revoke records in the log
12987  *   for a single block, only the last one counts, and if there is a log
12988  *   entry for a block beyond the last revoke, then that log entry still
12989  *   gets replayed.
12990  *
12991  * We can get interactions between revokes and new log data within a
12992  * single transaction:
12993  *
12994  * Block is revoked and then journaled:
12995  *   The desired end result is the journaling of the new block, so we
12996  *   cancel the revoke before the transaction commits.
12997  *
12998  * Block is journaled and then revoked:
12999  *   The revoke must take precedence over the write of the block, so we
13000  *   need either to cancel the journal entry or to write the revoke
13001  *   later in the log than the log block.  In this case, we choose the
13002  *   latter: journaling a block cancels any revoke record for that block
13003  *   in the current transaction, so any revoke for that block in the
13004  *   transaction must have happened after the block was journaled and so
13005  *   the revoke must take precedence.
13006  *
13007  * Block is revoked and then written as data:
13008  *   The data write is allowed to succeed, but the revoke is _not_
13009  *   cancelled.  We still need to prevent old log records from
13010  *   overwriting the new data.  We don't even need to clear the revoke
13011  *   bit here.
13012  *
13013  * Revoke information on buffers is a tri-state value:
13014  *
13015  * RevokeValid clear:   no cached revoke status, need to look it up
13016  * RevokeValid set, Revoked clear:
13017  *                      buffer has not been revoked, and cancel_revoke
13018  *                      need do nothing.
13019  * RevokeValid set, Revoked set:
13020  *                      buffer has been revoked.
13021  */
13022
13023 static kmem_cache_t *revoke_record_cache;
13024 static kmem_cache_t *revoke_table_cache;
13025
13026 /* Each revoke record represents one single revoked block.  During
13027    journal replay, this involves recording the transaction ID of the
13028    last transaction to revoke this block. */
13029
13030 struct jbd_revoke_record_s
13031 {
13032         struct list_head  hash;
13033         tid_t             sequence;     /* Used for recovery only */
13034         unsigned long     blocknr;
13035 };
13036
13037
13038 /* The revoke table is just a simple hash table of revoke records. */
13039 struct jbd_revoke_table_s
13040 {
13041         /* It is conceivable that we might want a larger hash table
13042          * for recovery.  Must be a power of two. */
13043         int               hash_size;
13044         int               hash_shift;
13045         struct list_head *hash_table;
13046 };
13047
13048
13049 /* Utility functions to maintain the revoke table */
13050
13051 /* Borrowed from buffer.c: this is a tried and tested block hash function */
13052 static inline int hash(journal_t *journal, unsigned long block)
13053 {
13054         struct jbd_revoke_table_s *table = journal->j_revoke;
13055         int hash_shift = table->hash_shift;
13056
13057         return ((block << (hash_shift - 6)) ^
13058                 (block >> 13) ^
13059                 (block << (hash_shift - 12))) & (table->hash_size - 1);
13060 }
13061
13062 static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
13063                               tid_t seq)
13064 {
13065         struct list_head *hash_list;
13066         struct jbd_revoke_record_s *record;
13067
13068         record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
13069         if (!record)
13070                 goto oom;
13071
13072         record->sequence = seq;
13073         record->blocknr = blocknr;
13074         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
13075         list_add(&record->hash, hash_list);
13076         return 0;
13077
13078 oom:
13079         return -ENOMEM;
13080 }
13081
13082 /* Find a revoke record in the journal's hash table. */
13083
13084 static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
13085                                                       unsigned long blocknr)
13086 {
13087         struct list_head *hash_list;
13088         struct jbd_revoke_record_s *record;
13089
13090         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
13091
13092         record = (struct jbd_revoke_record_s *) hash_list->next;
13093         while (&(record->hash) != hash_list) {
13094                 if (record->blocknr == blocknr)
13095                         return record;
13096                 record = (struct jbd_revoke_record_s *) record->hash.next;
13097         }
13098         return NULL;
13099 }
13100
13101 int journal_init_revoke_caches(void)
13102 {
13103         revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
13104         if (revoke_record_cache == 0)
13105                 return -ENOMEM;
13106
13107         revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
13108         if (revoke_table_cache == 0) {
13109                 do_cache_destroy(revoke_record_cache);
13110                 revoke_record_cache = NULL;
13111                 return -ENOMEM;
13112         }
13113         return 0;
13114 }
13115
13116 void journal_destroy_revoke_caches(void)
13117 {
13118         do_cache_destroy(revoke_record_cache);
13119         revoke_record_cache = 0;
13120         do_cache_destroy(revoke_table_cache);
13121         revoke_table_cache = 0;
13122 }
13123
13124 /* Initialise the revoke table for a given journal to a given size. */
13125
13126 int journal_init_revoke(journal_t *journal, int hash_size)
13127 {
13128         int shift, tmp;
13129
13130         J_ASSERT (journal->j_revoke == NULL);
13131
13132         journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
13133         if (!journal->j_revoke)
13134                 return -ENOMEM;
13135
13136         /* Check that the hash_size is a power of two */
13137         J_ASSERT ((hash_size & (hash_size-1)) == 0);
13138
13139         journal->j_revoke->hash_size = hash_size;
13140
13141         shift = 0;
13142         tmp = hash_size;
13143         while((tmp >>= 1UL) != 0UL)
13144                 shift++;
13145         journal->j_revoke->hash_shift = shift;
13146
13147         journal->j_revoke->hash_table = malloc(hash_size * sizeof(struct list_head));
13148         if (!journal->j_revoke->hash_table) {
13149                 free(journal->j_revoke);
13150                 journal->j_revoke = NULL;
13151                 return -ENOMEM;
13152         }
13153
13154         for (tmp = 0; tmp < hash_size; tmp++)
13155                 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
13156
13157         return 0;
13158 }
13159
13160 /* Destoy a journal's revoke table.  The table must already be empty! */
13161
13162 void journal_destroy_revoke(journal_t *journal)
13163 {
13164         struct jbd_revoke_table_s *table;
13165         struct list_head *hash_list;
13166         int i;
13167
13168         table = journal->j_revoke;
13169         if (!table)
13170                 return;
13171
13172         for (i=0; i<table->hash_size; i++) {
13173                 hash_list = &table->hash_table[i];
13174                 J_ASSERT (list_empty(hash_list));
13175         }
13176
13177         free(table->hash_table);
13178         free(table);
13179         journal->j_revoke = NULL;
13180 }
13181
13182 /*
13183  * Revoke support for recovery.
13184  *
13185  * Recovery needs to be able to:
13186  *
13187  *  record all revoke records, including the tid of the latest instance
13188  *  of each revoke in the journal
13189  *
13190  *  check whether a given block in a given transaction should be replayed
13191  *  (ie. has not been revoked by a revoke record in that or a subsequent
13192  *  transaction)
13193  *
13194  *  empty the revoke table after recovery.
13195  */
13196
13197 /*
13198  * First, setting revoke records.  We create a new revoke record for
13199  * every block ever revoked in the log as we scan it for recovery, and
13200  * we update the existing records if we find multiple revokes for a
13201  * single block.
13202  */
13203
13204 int journal_set_revoke(journal_t *journal, unsigned long blocknr,
13205                        tid_t sequence)
13206 {
13207         struct jbd_revoke_record_s *record;
13208
13209         record = find_revoke_record(journal, blocknr);
13210         if (record) {
13211                 /* If we have multiple occurences, only record the
13212                  * latest sequence number in the hashed record */
13213                 if (tid_gt(sequence, record->sequence))
13214                         record->sequence = sequence;
13215                 return 0;
13216         }
13217         return insert_revoke_hash(journal, blocknr, sequence);
13218 }
13219
13220 /*
13221  * Test revoke records.  For a given block referenced in the log, has
13222  * that block been revoked?  A revoke record with a given transaction
13223  * sequence number revokes all blocks in that transaction and earlier
13224  * ones, but later transactions still need replayed.
13225  */
13226
13227 int journal_test_revoke(journal_t *journal, unsigned long blocknr,
13228                         tid_t sequence)
13229 {
13230         struct jbd_revoke_record_s *record;
13231
13232         record = find_revoke_record(journal, blocknr);
13233         if (!record)
13234                 return 0;
13235         if (tid_gt(sequence, record->sequence))
13236                 return 0;
13237         return 1;
13238 }
13239
13240 /*
13241  * Finally, once recovery is over, we need to clear the revoke table so
13242  * that it can be reused by the running filesystem.
13243  */
13244
13245 void journal_clear_revoke(journal_t *journal)
13246 {
13247         int i;
13248         struct list_head *hash_list;
13249         struct jbd_revoke_record_s *record;
13250         struct jbd_revoke_table_s *revoke_var;
13251
13252         revoke_var = journal->j_revoke;
13253
13254         for (i = 0; i < revoke_var->hash_size; i++) {
13255                 hash_list = &revoke_var->hash_table[i];
13256                 while (!list_empty(hash_list)) {
13257                         record = (struct jbd_revoke_record_s*) hash_list->next;
13258                         list_del(&record->hash);
13259                         free(record);
13260                 }
13261         }
13262 }
13263
13264 /*
13265  * e2fsck.c - superblock checks
13266  */
13267
13268 #define MIN_CHECK 1
13269 #define MAX_CHECK 2
13270
13271 static void check_super_value(e2fsck_t ctx, const char *descr,
13272                               unsigned long value, int flags,
13273                               unsigned long min_val, unsigned long max_val)
13274 {
13275         struct          problem_context pctx;
13276
13277         if (((flags & MIN_CHECK) && (value < min_val)) ||
13278             ((flags & MAX_CHECK) && (value > max_val))) {
13279                 clear_problem_context(&pctx);
13280                 pctx.num = value;
13281                 pctx.str = descr;
13282                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
13283                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
13284         }
13285 }
13286
13287 /*
13288  * This routine may get stubbed out in special compilations of the
13289  * e2fsck code..
13290  */
13291 #ifndef EXT2_SPECIAL_DEVICE_SIZE
13292 static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
13293 {
13294         return (ext2fs_get_device_size(ctx->filesystem_name,
13295                                        EXT2_BLOCK_SIZE(ctx->fs->super),
13296                                        &ctx->num_blocks));
13297 }
13298 #endif
13299
13300 /*
13301  * helper function to release an inode
13302  */
13303 struct process_block_struct {
13304         e2fsck_t        ctx;
13305         char            *buf;
13306         struct problem_context *pctx;
13307         int             truncating;
13308         int             truncate_offset;
13309         e2_blkcnt_t     truncate_block;
13310         int             truncated_blocks;
13311         int             abort;
13312         errcode_t       errcode;
13313 };
13314
13315 static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
13316                                e2_blkcnt_t blockcnt,
13317                                blk_t    ref_blk FSCK_ATTR((unused)),
13318                                int      ref_offset FSCK_ATTR((unused)),
13319                                void *priv_data)
13320 {
13321         struct process_block_struct *pb;
13322         e2fsck_t                ctx;
13323         struct problem_context  *pctx;
13324         blk_t                   blk = *block_nr;
13325         int                     retval = 0;
13326
13327         pb = (struct process_block_struct *) priv_data;
13328         ctx = pb->ctx;
13329         pctx = pb->pctx;
13330
13331         pctx->blk = blk;
13332         pctx->blkcount = blockcnt;
13333
13334         if (HOLE_BLKADDR(blk))
13335                 return 0;
13336
13337         if ((blk < fs->super->s_first_data_block) ||
13338             (blk >= fs->super->s_blocks_count)) {
13339                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
13340         return_abort:
13341                 pb->abort = 1;
13342                 return BLOCK_ABORT;
13343         }
13344
13345         if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
13346                 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
13347                 goto return_abort;
13348         }
13349
13350         /*
13351          * If we are deleting an orphan, then we leave the fields alone.
13352          * If we are truncating an orphan, then update the inode fields
13353          * and clean up any partial block data.
13354          */
13355         if (pb->truncating) {
13356                 /*
13357                  * We only remove indirect blocks if they are
13358                  * completely empty.
13359                  */
13360                 if (blockcnt < 0) {
13361                         int     i, limit;
13362                         blk_t   *bp;
13363
13364                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
13365                                                         pb->buf);
13366                         if (pb->errcode)
13367                                 goto return_abort;
13368
13369                         limit = fs->blocksize >> 2;
13370                         for (i = 0, bp = (blk_t *) pb->buf;
13371                              i < limit;  i++, bp++)
13372                                 if (*bp)
13373                                         return 0;
13374                 }
13375                 /*
13376                  * We don't remove direct blocks until we've reached
13377                  * the truncation block.
13378                  */
13379                 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
13380                         return 0;
13381                 /*
13382                  * If part of the last block needs truncating, we do
13383                  * it here.
13384                  */
13385                 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
13386                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
13387                                                         pb->buf);
13388                         if (pb->errcode)
13389                                 goto return_abort;
13390                         memset(pb->buf + pb->truncate_offset, 0,
13391                                fs->blocksize - pb->truncate_offset);
13392                         pb->errcode = io_channel_write_blk(fs->io, blk, 1,
13393                                                          pb->buf);
13394                         if (pb->errcode)
13395                                 goto return_abort;
13396                 }
13397                 pb->truncated_blocks++;
13398                 *block_nr = 0;
13399                 retval |= BLOCK_CHANGED;
13400         }
13401
13402         ext2fs_block_alloc_stats(fs, blk, -1);
13403         return retval;
13404 }
13405
13406 /*
13407  * This function releases an inode.  Returns 1 if an inconsistency was
13408  * found.  If the inode has a link count, then it is being truncated and
13409  * not deleted.
13410  */
13411 static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
13412                                 struct ext2_inode *inode, char *block_buf,
13413                                 struct problem_context *pctx)
13414 {
13415         struct process_block_struct     pb;
13416         ext2_filsys                     fs = ctx->fs;
13417         errcode_t                       retval;
13418         __u32                           count;
13419
13420         if (!ext2fs_inode_has_valid_blocks(inode))
13421                 return 0;
13422
13423         pb.buf = block_buf + 3 * ctx->fs->blocksize;
13424         pb.ctx = ctx;
13425         pb.abort = 0;
13426         pb.errcode = 0;
13427         pb.pctx = pctx;
13428         if (inode->i_links_count) {
13429                 pb.truncating = 1;
13430                 pb.truncate_block = (e2_blkcnt_t)
13431                         ((((long long)inode->i_size_high << 32) +
13432                           inode->i_size + fs->blocksize - 1) /
13433                          fs->blocksize);
13434                 pb.truncate_offset = inode->i_size % fs->blocksize;
13435         } else {
13436                 pb.truncating = 0;
13437                 pb.truncate_block = 0;
13438                 pb.truncate_offset = 0;
13439         }
13440         pb.truncated_blocks = 0;
13441         retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
13442                                       block_buf, release_inode_block, &pb);
13443         if (retval) {
13444                 com_err("release_inode_blocks", retval,
13445                         _("while calling ext2fs_block_iterate for inode %d"),
13446                         ino);
13447                 return 1;
13448         }
13449         if (pb.abort)
13450                 return 1;
13451
13452         /* Refresh the inode since ext2fs_block_iterate may have changed it */
13453         e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
13454
13455         if (pb.truncated_blocks)
13456                 inode->i_blocks -= pb.truncated_blocks *
13457                         (fs->blocksize / 512);
13458
13459         if (inode->i_file_acl) {
13460                 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
13461                                                    block_buf, -1, &count);
13462                 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
13463                         retval = 0;
13464                         count = 1;
13465                 }
13466                 if (retval) {
13467                         com_err("release_inode_blocks", retval,
13468                 _("while calling ext2fs_adjust_ea_refocunt for inode %d"),
13469                                 ino);
13470                         return 1;
13471                 }
13472                 if (count == 0)
13473                         ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
13474                 inode->i_file_acl = 0;
13475         }
13476         return 0;
13477 }
13478
13479 /*
13480  * This function releases all of the orphan inodes.  It returns 1 if
13481  * it hit some error, and 0 on success.
13482  */
13483 static int release_orphan_inodes(e2fsck_t ctx)
13484 {
13485         ext2_filsys fs = ctx->fs;
13486         ext2_ino_t      ino, next_ino;
13487         struct ext2_inode inode;
13488         struct problem_context pctx;
13489         char *block_buf;
13490
13491         if ((ino = fs->super->s_last_orphan) == 0)
13492                 return 0;
13493
13494         /*
13495          * Win or lose, we won't be using the head of the orphan inode
13496          * list again.
13497          */
13498         fs->super->s_last_orphan = 0;
13499         ext2fs_mark_super_dirty(fs);
13500
13501         /*
13502          * If the filesystem contains errors, don't run the orphan
13503          * list, since the orphan list can't be trusted; and we're
13504          * going to be running a full e2fsck run anyway...
13505          */
13506         if (fs->super->s_state & EXT2_ERROR_FS)
13507                 return 0;
13508
13509         if ((ino < EXT2_FIRST_INODE(fs->super)) ||
13510             (ino > fs->super->s_inodes_count)) {
13511                 clear_problem_context(&pctx);
13512                 pctx.ino = ino;
13513                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
13514                 return 1;
13515         }
13516
13517         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
13518                                                     "block iterate buffer");
13519         e2fsck_read_bitmaps(ctx);
13520
13521         while (ino) {
13522                 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
13523                 clear_problem_context(&pctx);
13524                 pctx.ino = ino;
13525                 pctx.inode = &inode;
13526                 pctx.str = inode.i_links_count ? _("Truncating") :
13527                         _("Clearing");
13528
13529                 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
13530
13531                 next_ino = inode.i_dtime;
13532                 if (next_ino &&
13533                     ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
13534                      (next_ino > fs->super->s_inodes_count))) {
13535                         pctx.ino = next_ino;
13536                         fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
13537                         goto return_abort;
13538                 }
13539
13540                 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
13541                         goto return_abort;
13542
13543                 if (!inode.i_links_count) {
13544                         ext2fs_inode_alloc_stats2(fs, ino, -1,
13545                                                   LINUX_S_ISDIR(inode.i_mode));
13546                         inode.i_dtime = time(0);
13547                 } else {
13548                         inode.i_dtime = 0;
13549                 }
13550                 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
13551                 ino = next_ino;
13552         }
13553         ext2fs_free_mem(&block_buf);
13554         return 0;
13555 return_abort:
13556         ext2fs_free_mem(&block_buf);
13557         return 1;
13558 }
13559
13560 /*
13561  * Check the resize inode to make sure it is sane.  We check both for
13562  * the case where on-line resizing is not enabled (in which case the
13563  * resize inode should be cleared) as well as the case where on-line
13564  * resizing is enabled.
13565  */
13566 static void check_resize_inode(e2fsck_t ctx)
13567 {
13568         ext2_filsys fs = ctx->fs;
13569         struct ext2_inode inode;
13570         struct problem_context  pctx;
13571         int             i, j, gdt_off, ind_off;
13572         blk_t           blk, pblk, expect;
13573         __u32           *dind_buf = 0, *ind_buf;
13574         errcode_t       retval;
13575
13576         clear_problem_context(&pctx);
13577
13578         /*
13579          * If the resize inode feature isn't set, then
13580          * s_reserved_gdt_blocks must be zero.
13581          */
13582         if (!(fs->super->s_feature_compat &
13583               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
13584                 if (fs->super->s_reserved_gdt_blocks) {
13585                         pctx.num = fs->super->s_reserved_gdt_blocks;
13586                         if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
13587                                         &pctx)) {
13588                                 fs->super->s_reserved_gdt_blocks = 0;
13589                                 ext2fs_mark_super_dirty(fs);
13590                         }
13591                 }
13592         }
13593
13594         /* Read the resizde inode */
13595         pctx.ino = EXT2_RESIZE_INO;
13596         retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
13597         if (retval) {
13598                 if (fs->super->s_feature_compat &
13599                     EXT2_FEATURE_COMPAT_RESIZE_INODE)
13600                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
13601                 return;
13602         }
13603
13604         /*
13605          * If the resize inode feature isn't set, check to make sure
13606          * the resize inode is cleared; then we're done.
13607          */
13608         if (!(fs->super->s_feature_compat &
13609               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
13610                 for (i=0; i < EXT2_N_BLOCKS; i++) {
13611                         if (inode.i_block[i])
13612                                 break;
13613                 }
13614                 if ((i < EXT2_N_BLOCKS) &&
13615                     fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
13616                         memset(&inode, 0, sizeof(inode));
13617                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
13618                                            "clear_resize");
13619                 }
13620                 return;
13621         }
13622
13623         /*
13624          * The resize inode feature is enabled; check to make sure the
13625          * only block in use is the double indirect block
13626          */
13627         blk = inode.i_block[EXT2_DIND_BLOCK];
13628         for (i=0; i < EXT2_N_BLOCKS; i++) {
13629                 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
13630                         break;
13631         }
13632         if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
13633             !(inode.i_mode & LINUX_S_IFREG) ||
13634             (blk < fs->super->s_first_data_block ||
13635              blk >= fs->super->s_blocks_count)) {
13636         resize_inode_invalid:
13637                 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
13638                         memset(&inode, 0, sizeof(inode));
13639                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
13640                                            "clear_resize");
13641                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
13642                 }
13643                 if (!(ctx->options & E2F_OPT_READONLY)) {
13644                         fs->super->s_state &= ~EXT2_VALID_FS;
13645                         ext2fs_mark_super_dirty(fs);
13646                 }
13647                 goto cleanup;
13648         }
13649         dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
13650                                                     "resize dind buffer");
13651         ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
13652
13653         retval = ext2fs_read_ind_block(fs, blk, dind_buf);
13654         if (retval)
13655                 goto resize_inode_invalid;
13656
13657         gdt_off = fs->desc_blocks;
13658         pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
13659         for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
13660              i++, gdt_off++, pblk++) {
13661                 gdt_off %= fs->blocksize/4;
13662                 if (dind_buf[gdt_off] != pblk)
13663                         goto resize_inode_invalid;
13664                 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
13665                 if (retval)
13666                         goto resize_inode_invalid;
13667                 ind_off = 0;
13668                 for (j = 1; j < fs->group_desc_count; j++) {
13669                         if (!ext2fs_bg_has_super(fs, j))
13670                                 continue;
13671                         expect = pblk + (j * fs->super->s_blocks_per_group);
13672                         if (ind_buf[ind_off] != expect)
13673                                 goto resize_inode_invalid;
13674                         ind_off++;
13675                 }
13676         }
13677
13678 cleanup:
13679         if (dind_buf)
13680                 ext2fs_free_mem(&dind_buf);
13681
13682  }
13683
13684 static void check_super_block(e2fsck_t ctx)
13685 {
13686         ext2_filsys fs = ctx->fs;
13687         blk_t   first_block, last_block;
13688         struct ext2_super_block *sb = fs->super;
13689         struct ext2_group_desc *gd;
13690         blk_t   blocks_per_group = fs->super->s_blocks_per_group;
13691         blk_t   bpg_max;
13692         int     inodes_per_block;
13693         int     ipg_max;
13694         int     inode_size;
13695         dgrp_t  i;
13696         blk_t   should_be;
13697         struct problem_context  pctx;
13698         __u32   free_blocks = 0, free_inodes = 0;
13699
13700         inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
13701         ipg_max = inodes_per_block * (blocks_per_group - 4);
13702         if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
13703                 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
13704         bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
13705         if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
13706                 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
13707
13708         ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
13709                  sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
13710         ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
13711                  sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
13712         ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
13713                 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
13714
13715         clear_problem_context(&pctx);
13716
13717         /*
13718          * Verify the super block constants...
13719          */
13720         check_super_value(ctx, "inodes_count", sb->s_inodes_count,
13721                           MIN_CHECK, 1, 0);
13722         check_super_value(ctx, "blocks_count", sb->s_blocks_count,
13723                           MIN_CHECK, 1, 0);
13724         check_super_value(ctx, "first_data_block", sb->s_first_data_block,
13725                           MAX_CHECK, 0, sb->s_blocks_count);
13726         check_super_value(ctx, "log_block_size", sb->s_log_block_size,
13727                           MIN_CHECK | MAX_CHECK, 0,
13728                           EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
13729         check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
13730                           MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
13731         check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
13732                           MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
13733                           bpg_max);
13734         check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
13735                           MIN_CHECK | MAX_CHECK, 8, bpg_max);
13736         check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
13737                           MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
13738         check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
13739                           MAX_CHECK, 0, sb->s_blocks_count / 2);
13740         check_super_value(ctx, "reserved_gdt_blocks",
13741                           sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
13742                           fs->blocksize/4);
13743         inode_size = EXT2_INODE_SIZE(sb);
13744         check_super_value(ctx, "inode_size",
13745                           inode_size, MIN_CHECK | MAX_CHECK,
13746                           EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
13747         if (inode_size & (inode_size - 1)) {
13748                 pctx.num = inode_size;
13749                 pctx.str = "inode_size";
13750                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
13751                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
13752                 return;
13753         }
13754
13755         if (!ctx->num_blocks) {
13756                 pctx.errcode = e2fsck_get_device_size(ctx);
13757                 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
13758                         fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
13759                         ctx->flags |= E2F_FLAG_ABORT;
13760                         return;
13761                 }
13762                 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
13763                     (ctx->num_blocks < sb->s_blocks_count)) {
13764                         pctx.blk = sb->s_blocks_count;
13765                         pctx.blk2 = ctx->num_blocks;
13766                         if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
13767                                 ctx->flags |= E2F_FLAG_ABORT;
13768                                 return;
13769                         }
13770                 }
13771         }
13772
13773         if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
13774                 pctx.blk = EXT2_BLOCK_SIZE(sb);
13775                 pctx.blk2 = EXT2_FRAG_SIZE(sb);
13776                 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
13777                 ctx->flags |= E2F_FLAG_ABORT;
13778                 return;
13779         }
13780
13781         should_be = sb->s_frags_per_group >>
13782                 (sb->s_log_block_size - sb->s_log_frag_size);
13783         if (sb->s_blocks_per_group != should_be) {
13784                 pctx.blk = sb->s_blocks_per_group;
13785                 pctx.blk2 = should_be;
13786                 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
13787                 ctx->flags |= E2F_FLAG_ABORT;
13788                 return;
13789         }
13790
13791         should_be = (sb->s_log_block_size == 0) ? 1 : 0;
13792         if (sb->s_first_data_block != should_be) {
13793                 pctx.blk = sb->s_first_data_block;
13794                 pctx.blk2 = should_be;
13795                 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
13796                 ctx->flags |= E2F_FLAG_ABORT;
13797                 return;
13798         }
13799
13800         should_be = sb->s_inodes_per_group * fs->group_desc_count;
13801         if (sb->s_inodes_count != should_be) {
13802                 pctx.ino = sb->s_inodes_count;
13803                 pctx.ino2 = should_be;
13804                 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
13805                         sb->s_inodes_count = should_be;
13806                         ext2fs_mark_super_dirty(fs);
13807                 }
13808         }
13809
13810         /*
13811          * Verify the group descriptors....
13812          */
13813         first_block =  sb->s_first_data_block;
13814         last_block = first_block + blocks_per_group;
13815
13816         for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
13817                 pctx.group = i;
13818
13819                 if (i == fs->group_desc_count - 1)
13820                         last_block = sb->s_blocks_count;
13821                 if ((gd->bg_block_bitmap < first_block) ||
13822                     (gd->bg_block_bitmap >= last_block)) {
13823                         pctx.blk = gd->bg_block_bitmap;
13824                         if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
13825                                 gd->bg_block_bitmap = 0;
13826                 }
13827                 if (gd->bg_block_bitmap == 0) {
13828                         ctx->invalid_block_bitmap_flag[i]++;
13829                         ctx->invalid_bitmaps++;
13830                 }
13831                 if ((gd->bg_inode_bitmap < first_block) ||
13832                     (gd->bg_inode_bitmap >= last_block)) {
13833                         pctx.blk = gd->bg_inode_bitmap;
13834                         if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
13835                                 gd->bg_inode_bitmap = 0;
13836                 }
13837                 if (gd->bg_inode_bitmap == 0) {
13838                         ctx->invalid_inode_bitmap_flag[i]++;
13839                         ctx->invalid_bitmaps++;
13840                 }
13841                 if ((gd->bg_inode_table < first_block) ||
13842                     ((gd->bg_inode_table +
13843                       fs->inode_blocks_per_group - 1) >= last_block)) {
13844                         pctx.blk = gd->bg_inode_table;
13845                         if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
13846                                 gd->bg_inode_table = 0;
13847                 }
13848                 if (gd->bg_inode_table == 0) {
13849                         ctx->invalid_inode_table_flag[i]++;
13850                         ctx->invalid_bitmaps++;
13851                 }
13852                 free_blocks += gd->bg_free_blocks_count;
13853                 free_inodes += gd->bg_free_inodes_count;
13854                 first_block += sb->s_blocks_per_group;
13855                 last_block += sb->s_blocks_per_group;
13856
13857                 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
13858                     (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
13859                     (gd->bg_used_dirs_count > sb->s_inodes_per_group))
13860                         ext2fs_unmark_valid(fs);
13861
13862         }
13863
13864         /*
13865          * Update the global counts from the block group counts.  This
13866          * is needed for an experimental patch which eliminates
13867          * locking the entire filesystem when allocating blocks or
13868          * inodes; if the filesystem is not unmounted cleanly, the
13869          * global counts may not be accurate.
13870          */
13871         if ((free_blocks != sb->s_free_blocks_count) ||
13872             (free_inodes != sb->s_free_inodes_count)) {
13873                 if (ctx->options & E2F_OPT_READONLY)
13874                         ext2fs_unmark_valid(fs);
13875                 else {
13876                         sb->s_free_blocks_count = free_blocks;
13877                         sb->s_free_inodes_count = free_inodes;
13878                         ext2fs_mark_super_dirty(fs);
13879                 }
13880         }
13881
13882         if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
13883             (sb->s_free_inodes_count > sb->s_inodes_count))
13884                 ext2fs_unmark_valid(fs);
13885
13886
13887         /*
13888          * If we have invalid bitmaps, set the error state of the
13889          * filesystem.
13890          */
13891         if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
13892                 sb->s_state &= ~EXT2_VALID_FS;
13893                 ext2fs_mark_super_dirty(fs);
13894         }
13895
13896         clear_problem_context(&pctx);
13897
13898 #ifndef EXT2_SKIP_UUID
13899         /*
13900          * If the UUID field isn't assigned, assign it.
13901          */
13902         if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
13903                 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
13904                         uuid_generate(sb->s_uuid);
13905                         ext2fs_mark_super_dirty(fs);
13906                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
13907                 }
13908         }
13909 #endif
13910
13911         /*
13912          * For the Hurd, check to see if the filetype option is set,
13913          * since it doesn't support it.
13914          */
13915         if (!(ctx->options & E2F_OPT_READONLY) &&
13916             fs->super->s_creator_os == EXT2_OS_HURD &&
13917             (fs->super->s_feature_incompat &
13918              EXT2_FEATURE_INCOMPAT_FILETYPE)) {
13919                 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
13920                         fs->super->s_feature_incompat &=
13921                                 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
13922                         ext2fs_mark_super_dirty(fs);
13923
13924                 }
13925         }
13926
13927         /*
13928          * If we have any of the compatibility flags set, we need to have a
13929          * revision 1 filesystem.  Most kernels will not check the flags on
13930          * a rev 0 filesystem and we may have corruption issues because of
13931          * the incompatible changes to the filesystem.
13932          */
13933         if (!(ctx->options & E2F_OPT_READONLY) &&
13934             fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
13935             (fs->super->s_feature_compat ||
13936              fs->super->s_feature_ro_compat ||
13937              fs->super->s_feature_incompat) &&
13938             fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
13939                 ext2fs_update_dynamic_rev(fs);
13940                 ext2fs_mark_super_dirty(fs);
13941         }
13942
13943         check_resize_inode(ctx);
13944
13945         /*
13946          * Clean up any orphan inodes, if present.
13947          */
13948         if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
13949                 fs->super->s_state &= ~EXT2_VALID_FS;
13950                 ext2fs_mark_super_dirty(fs);
13951         }
13952
13953         /*
13954          * Move the ext3 journal file, if necessary.
13955          */
13956         e2fsck_move_ext3_journal(ctx);
13957         return;
13958 }
13959
13960 /*
13961  * swapfs.c --- byte-swap an ext2 filesystem
13962  */
13963
13964 #ifdef ENABLE_SWAPFS
13965
13966 struct swap_block_struct {
13967         ext2_ino_t      ino;
13968         int             isdir;
13969         errcode_t       errcode;
13970         char            *dir_buf;
13971         struct ext2_inode *inode;
13972 };
13973
13974 /*
13975  * This is a helper function for block_iterate.  We mark all of the
13976  * indirect and direct blocks as changed, so that block_iterate will
13977  * write them out.
13978  */
13979 static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
13980                       void *priv_data)
13981 {
13982         errcode_t       retval;
13983
13984         struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
13985
13986         if (sb->isdir && (blockcnt >= 0) && *block_nr) {
13987                 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
13988                 if (retval) {
13989                         sb->errcode = retval;
13990                         return BLOCK_ABORT;
13991                 }
13992                 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
13993                 if (retval) {
13994                         sb->errcode = retval;
13995                         return BLOCK_ABORT;
13996                 }
13997         }
13998         if (blockcnt >= 0) {
13999                 if (blockcnt < EXT2_NDIR_BLOCKS)
14000                         return 0;
14001                 return BLOCK_CHANGED;
14002         }
14003         if (blockcnt == BLOCK_COUNT_IND) {
14004                 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
14005                         return 0;
14006                 return BLOCK_CHANGED;
14007         }
14008         if (blockcnt == BLOCK_COUNT_DIND) {
14009                 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
14010                         return 0;
14011                 return BLOCK_CHANGED;
14012         }
14013         if (blockcnt == BLOCK_COUNT_TIND) {
14014                 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
14015                         return 0;
14016                 return BLOCK_CHANGED;
14017         }
14018         return BLOCK_CHANGED;
14019 }
14020
14021 /*
14022  * This function is responsible for byte-swapping all of the indirect,
14023  * block pointers.  It is also responsible for byte-swapping directories.
14024  */
14025 static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
14026                               struct ext2_inode *inode)
14027 {
14028         errcode_t                       retval;
14029         struct swap_block_struct        sb;
14030
14031         sb.ino = ino;
14032         sb.inode = inode;
14033         sb.dir_buf = block_buf + ctx->fs->blocksize*3;
14034         sb.errcode = 0;
14035         sb.isdir = 0;
14036         if (LINUX_S_ISDIR(inode->i_mode))
14037                 sb.isdir = 1;
14038
14039         retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
14040                                       swap_block, &sb);
14041         if (retval) {
14042                 com_err("swap_inode_blocks", retval,
14043                         _("while calling ext2fs_block_iterate"));
14044                 ctx->flags |= E2F_FLAG_ABORT;
14045                 return;
14046         }
14047         if (sb.errcode) {
14048                 com_err("swap_inode_blocks", sb.errcode,
14049                         _("while calling iterator function"));
14050                 ctx->flags |= E2F_FLAG_ABORT;
14051                 return;
14052         }
14053 }
14054
14055 static void swap_inodes(e2fsck_t ctx)
14056 {
14057         ext2_filsys fs = ctx->fs;
14058         dgrp_t                  group;
14059         unsigned int            i;
14060         ext2_ino_t              ino = 1;
14061         char                    *buf, *block_buf;
14062         errcode_t               retval;
14063         struct ext2_inode *     inode;
14064
14065         e2fsck_use_inode_shortcuts(ctx, 1);
14066
14067         retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
14068                                 &buf);
14069         if (retval) {
14070                 com_err("swap_inodes", retval,
14071                         _("while allocating inode buffer"));
14072                 ctx->flags |= E2F_FLAG_ABORT;
14073                 return;
14074         }
14075         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
14076                                                     "block interate buffer");
14077         for (group = 0; group < fs->group_desc_count; group++) {
14078                 retval = io_channel_read_blk(fs->io,
14079                       fs->group_desc[group].bg_inode_table,
14080                       fs->inode_blocks_per_group, buf);
14081                 if (retval) {
14082                         com_err("swap_inodes", retval,
14083                                 _("while reading inode table (group %d)"),
14084                                 group);
14085                         ctx->flags |= E2F_FLAG_ABORT;
14086                         return;
14087                 }
14088                 inode = (struct ext2_inode *) buf;
14089                 for (i=0; i < fs->super->s_inodes_per_group;
14090                      i++, ino++, inode++) {
14091                         ctx->stashed_ino = ino;
14092                         ctx->stashed_inode = inode;
14093
14094                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
14095                                 ext2fs_swap_inode(fs, inode, inode, 0);
14096
14097                         /*
14098                          * Skip deleted files.
14099                          */
14100                         if (inode->i_links_count == 0)
14101                                 continue;
14102
14103                         if (LINUX_S_ISDIR(inode->i_mode) ||
14104                             ((inode->i_block[EXT2_IND_BLOCK] ||
14105                               inode->i_block[EXT2_DIND_BLOCK] ||
14106                               inode->i_block[EXT2_TIND_BLOCK]) &&
14107                              ext2fs_inode_has_valid_blocks(inode)))
14108                                 swap_inode_blocks(ctx, ino, block_buf, inode);
14109
14110                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
14111                                 return;
14112
14113                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
14114                                 ext2fs_swap_inode(fs, inode, inode, 1);
14115                 }
14116                 retval = io_channel_write_blk(fs->io,
14117                       fs->group_desc[group].bg_inode_table,
14118                       fs->inode_blocks_per_group, buf);
14119                 if (retval) {
14120                         com_err("swap_inodes", retval,
14121                                 _("while writing inode table (group %d)"),
14122                                 group);
14123                         ctx->flags |= E2F_FLAG_ABORT;
14124                         return;
14125                 }
14126         }
14127         ext2fs_free_mem(&buf);
14128         ext2fs_free_mem(&block_buf);
14129         e2fsck_use_inode_shortcuts(ctx, 0);
14130         ext2fs_flush_icache(fs);
14131 }
14132
14133 #if defined(__powerpc__) && defined(EXT2FS_ENABLE_SWAPFS)
14134 /*
14135  * On the PowerPC, the big-endian variant of the ext2 filesystem
14136  * has its bitmaps stored as 32-bit words with bit 0 as the LSB
14137  * of each word.  Thus a bitmap with only bit 0 set would be, as
14138  * a string of bytes, 00 00 00 01 00 ...
14139  * To cope with this, we byte-reverse each word of a bitmap if
14140  * we have a big-endian filesystem, that is, if we are *not*
14141  * byte-swapping other word-sized numbers.
14142  */
14143 #define EXT2_BIG_ENDIAN_BITMAPS
14144 #endif
14145
14146 #ifdef EXT2_BIG_ENDIAN_BITMAPS
14147 static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
14148 {
14149         __u32 *p = (__u32 *) bmap->bitmap;
14150         int n, nbytes = (bmap->end - bmap->start + 7) / 8;
14151
14152         for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
14153                 *p = ext2fs_swab32(*p);
14154 }
14155 #endif
14156
14157
14158 #ifdef ENABLE_SWAPFS
14159 static void swap_filesys(e2fsck_t ctx)
14160 {
14161         ext2_filsys fs = ctx->fs;
14162 #ifdef RESOURCE_TRACK
14163         struct resource_track   rtrack;
14164
14165         init_resource_track(&rtrack);
14166 #endif
14167
14168         if (!(ctx->options & E2F_OPT_PREEN))
14169                 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
14170
14171 #ifdef MTRACE
14172         mtrace_print("Byte swap");
14173 #endif
14174
14175         if (fs->super->s_mnt_count) {
14176                 fprintf(stderr, _("%s: the filesystem must be freshly "
14177                         "checked using fsck\n"
14178                         "and not mounted before trying to "
14179                         "byte-swap it.\n"), ctx->device_name);
14180                 ctx->flags |= E2F_FLAG_ABORT;
14181                 return;
14182         }
14183         if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
14184                 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
14185                                EXT2_FLAG_SWAP_BYTES_WRITE);
14186                 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
14187         } else {
14188                 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
14189                 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
14190         }
14191         swap_inodes(ctx);
14192         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
14193                 return;
14194         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
14195                 fs->flags |= EXT2_FLAG_SWAP_BYTES;
14196         fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
14197                        EXT2_FLAG_SWAP_BYTES_WRITE);
14198
14199 #ifdef EXT2_BIG_ENDIAN_BITMAPS
14200         e2fsck_read_bitmaps(ctx);
14201         ext2fs_swap_bitmap(fs->inode_map);
14202         ext2fs_swap_bitmap(fs->block_map);
14203         fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
14204 #endif
14205         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
14206         ext2fs_flush(fs);
14207         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
14208
14209 #ifdef RESOURCE_TRACK
14210         if (ctx->options & E2F_OPT_TIME2)
14211                 print_resource_track(_("Byte swap"), &rtrack);
14212 #endif
14213 }
14214 #endif  /* ENABLE_SWAPFS */
14215
14216 #endif
14217
14218 /*
14219  * util.c --- miscellaneous utilities
14220  */
14221
14222 #ifdef HAVE_CONIO_H
14223 #undef HAVE_TERMIOS_H
14224 #include <conio.h>
14225 #define read_a_char()   getch()
14226 #else
14227 #ifdef HAVE_TERMIOS_H
14228 #include <termios.h>
14229 #endif
14230 #endif
14231
14232 #if 0
14233 void fatal_error(e2fsck_t ctx, const char *msg)
14234 {
14235         if (msg)
14236                 fprintf (stderr, "e2fsck: %s\n", msg);
14237         if (ctx->fs && ctx->fs->io) {
14238                 if (ctx->fs->io->magic == EXT2_ET_MAGIC_IO_CHANNEL)
14239                         io_channel_flush(ctx->fs->io);
14240                 else
14241                         fprintf(stderr, "e2fsck: io manager magic bad!\n");
14242         }
14243         ctx->flags |= E2F_FLAG_ABORT;
14244         if (ctx->flags & E2F_FLAG_SETJMP_OK)
14245                 longjmp(ctx->abort_loc, 1);
14246         exit(EXIT_ERROR);
14247 }
14248 #endif
14249
14250 void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
14251                              const char *description)
14252 {
14253         void *ret;
14254         char buf[256];
14255
14256 #ifdef DEBUG_ALLOCATE_MEMORY
14257         printf("Allocating %d bytes for %s...\n", size, description);
14258 #endif
14259         ret = malloc(size);
14260         if (!ret) {
14261                 sprintf(buf, "Can't allocate %s\n", description);
14262                 fatal_error(ctx, buf);
14263         }
14264         memset(ret, 0, size);
14265         return ret;
14266 }
14267
14268 static char *string_copy(const char *str, int len)
14269 {
14270         char    *ret;
14271
14272         if (!str)
14273                 return NULL;
14274         if (!len)
14275                 len = strlen(str);
14276         ret = malloc(len+1);
14277         if (ret) {
14278                 strncpy(ret, str, len);
14279                 ret[len] = 0;
14280         }
14281         return ret;
14282 }
14283
14284 #ifndef HAVE_CONIO_H
14285 static int read_a_char(void)
14286 {
14287         char    c;
14288         int     r;
14289         int     fail = 0;
14290
14291         while(1) {
14292                 if (e2fsck_global_ctx &&
14293                     (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
14294                         return 3;
14295                 }
14296                 r = read(0, &c, 1);
14297                 if (r == 1)
14298                         return c;
14299                 if (fail++ > 100)
14300                         break;
14301         }
14302         return EOF;
14303 }
14304 #endif
14305
14306 static int ask_yn(const char * string, int def)
14307 {
14308         int             c;
14309         const char      *defstr;
14310         static const char short_yes[] = "yY";
14311         static const char short_no[] = "nN";
14312
14313 #ifdef HAVE_TERMIOS_H
14314         struct termios  termios, tmp;
14315
14316         tcgetattr (0, &termios);
14317         tmp = termios;
14318         tmp.c_lflag &= ~(ICANON | ECHO);
14319         tmp.c_cc[VMIN] = 1;
14320         tmp.c_cc[VTIME] = 0;
14321         tcsetattr (0, TCSANOW, &tmp);
14322 #endif
14323
14324         if (def == 1)
14325                 defstr = "<y>";
14326         else if (def == 0)
14327                 defstr = "<n>";
14328         else
14329                 defstr = " (y/n)";
14330         printf("%s%s? ", string, defstr);
14331         while (1) {
14332                 fflush (stdout);
14333                 if ((c = read_a_char()) == EOF)
14334                         break;
14335                 if (c == 3) {
14336 #ifdef HAVE_TERMIOS_H
14337                         tcsetattr (0, TCSANOW, &termios);
14338 #endif
14339                         if (e2fsck_global_ctx &&
14340                             e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
14341                                 puts("\n");
14342                                 longjmp(e2fsck_global_ctx->abort_loc, 1);
14343                         }
14344                         puts(_("cancelled!\n"));
14345                         return 0;
14346                 }
14347                 if (strchr(short_yes, (char) c)) {
14348                         def = 1;
14349                         break;
14350                 }
14351                 else if (strchr(short_no, (char) c)) {
14352                         def = 0;
14353                         break;
14354                 }
14355                 else if ((c == ' ' || c == '\n') && (def != -1))
14356                         break;
14357         }
14358         if (def)
14359                 puts("yes\n");
14360         else
14361                 puts ("no\n");
14362 #ifdef HAVE_TERMIOS_H
14363         tcsetattr (0, TCSANOW, &termios);
14364 #endif
14365         return def;
14366 }
14367
14368 int ask (e2fsck_t ctx, const char * string, int def)
14369 {
14370         if (ctx->options & E2F_OPT_NO) {
14371                 printf (_("%s? no\n\n"), string);
14372                 return 0;
14373         }
14374         if (ctx->options & E2F_OPT_YES) {
14375                 printf (_("%s? yes\n\n"), string);
14376                 return 1;
14377         }
14378         if (ctx->options & E2F_OPT_PREEN) {
14379                 printf ("%s? %s\n\n", string, def ? _("yes") : _("no"));
14380                 return def;
14381         }
14382         return ask_yn(string, def);
14383 }
14384
14385 void e2fsck_read_bitmaps(e2fsck_t ctx)
14386 {
14387         ext2_filsys fs = ctx->fs;
14388         errcode_t       retval;
14389
14390         if (ctx->invalid_bitmaps) {
14391                 com_err(ctx->program_name, 0,
14392                     _("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
14393                         ctx->device_name);
14394                 fatal_error(ctx, 0);
14395         }
14396
14397         ehandler_operation(_("reading inode and block bitmaps"));
14398         retval = ext2fs_read_bitmaps(fs);
14399         ehandler_operation(0);
14400         if (retval) {
14401                 com_err(ctx->program_name, retval,
14402                         _("while retrying to read bitmaps for %s"),
14403                         ctx->device_name);
14404                 fatal_error(ctx, 0);
14405         }
14406 }
14407
14408 static void e2fsck_write_bitmaps(e2fsck_t ctx)
14409 {
14410         ext2_filsys fs = ctx->fs;
14411         errcode_t       retval;
14412
14413         if (ext2fs_test_bb_dirty(fs)) {
14414                 ehandler_operation(_("writing block bitmaps"));
14415                 retval = ext2fs_write_block_bitmap(fs);
14416                 ehandler_operation(0);
14417                 if (retval) {
14418                         com_err(ctx->program_name, retval,
14419                             _("while retrying to write block bitmaps for %s"),
14420                                 ctx->device_name);
14421                         fatal_error(ctx, 0);
14422                 }
14423         }
14424
14425         if (ext2fs_test_ib_dirty(fs)) {
14426                 ehandler_operation(_("writing inode bitmaps"));
14427                 retval = ext2fs_write_inode_bitmap(fs);
14428                 ehandler_operation(0);
14429                 if (retval) {
14430                         com_err(ctx->program_name, retval,
14431                             _("while retrying to write inode bitmaps for %s"),
14432                                 ctx->device_name);
14433                         fatal_error(ctx, 0);
14434                 }
14435         }
14436 }
14437
14438 void preenhalt(e2fsck_t ctx)
14439 {
14440         ext2_filsys fs = ctx->fs;
14441
14442         if (!(ctx->options & E2F_OPT_PREEN))
14443                 return;
14444         fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
14445                 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
14446                ctx->device_name);
14447         if (fs != NULL) {
14448                 fs->super->s_state |= EXT2_ERROR_FS;
14449                 ext2fs_mark_super_dirty(fs);
14450                 ext2fs_close(fs);
14451         }
14452         exit(EXIT_UNCORRECTED);
14453 }
14454
14455 #ifdef RESOURCE_TRACK
14456 void init_resource_track(struct resource_track *track)
14457 {
14458 #ifdef HAVE_GETRUSAGE
14459         struct rusage r;
14460 #endif
14461
14462         track->brk_start = sbrk(0);
14463         gettimeofday(&track->time_start, 0);
14464 #ifdef HAVE_GETRUSAGE
14465 #ifdef sun
14466         memset(&r, 0, sizeof(struct rusage));
14467 #endif
14468         getrusage(RUSAGE_SELF, &r);
14469         track->user_start = r.ru_utime;
14470         track->system_start = r.ru_stime;
14471 #else
14472         track->user_start.tv_sec = track->user_start.tv_usec = 0;
14473         track->system_start.tv_sec = track->system_start.tv_usec = 0;
14474 #endif
14475 }
14476
14477 static _INLINE_ float timeval_subtract(struct timeval *tv1,
14478                                        struct timeval *tv2)
14479 {
14480         return ((tv1->tv_sec - tv2->tv_sec) +
14481                 ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
14482 }
14483
14484 void print_resource_track(const char *desc, struct resource_track *track)
14485 {
14486 #ifdef HAVE_GETRUSAGE
14487         struct rusage r;
14488 #endif
14489 #ifdef HAVE_MALLINFO
14490         struct mallinfo malloc_info;
14491 #endif
14492         struct timeval time_end;
14493
14494         gettimeofday(&time_end, 0);
14495
14496         if (desc)
14497                 printf("%s: ", desc);
14498
14499 #ifdef HAVE_MALLINFO
14500 #define kbytes(x)       (((x) + 1023) / 1024)
14501
14502         malloc_info = mallinfo();
14503         printf(_("Memory used: %dk/%dk (%dk/%dk), "),
14504                kbytes(malloc_info.arena), kbytes(malloc_info.hblkhd),
14505                kbytes(malloc_info.uordblks), kbytes(malloc_info.fordblks));
14506 #else
14507         printf(_("Memory used: %d, "),
14508                (int) (((char *) sbrk(0)) - ((char *) track->brk_start)));
14509 #endif
14510 #ifdef HAVE_GETRUSAGE
14511         getrusage(RUSAGE_SELF, &r);
14512
14513         printf(_("time: %5.2f/%5.2f/%5.2f\n"),
14514                timeval_subtract(&time_end, &track->time_start),
14515                timeval_subtract(&r.ru_utime, &track->user_start),
14516                timeval_subtract(&r.ru_stime, &track->system_start));
14517 #else
14518         printf(_("elapsed time: %6.3f\n"),
14519                timeval_subtract(&time_end, &track->time_start));
14520 #endif
14521 }
14522 #endif /* RESOURCE_TRACK */
14523
14524 void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
14525                               struct ext2_inode * inode, const char *proc)
14526 {
14527         int retval;
14528
14529         retval = ext2fs_read_inode(ctx->fs, ino, inode);
14530         if (retval) {
14531                 com_err("ext2fs_read_inode", retval,
14532                         _("while reading inode %ld in %s"), ino, proc);
14533                 fatal_error(ctx, 0);
14534         }
14535 }
14536
14537 extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
14538                                struct ext2_inode * inode, int bufsize,
14539                                const char *proc)
14540 {
14541         int retval;
14542
14543         retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
14544         if (retval) {
14545                 com_err("ext2fs_write_inode", retval,
14546                         _("while writing inode %ld in %s"), ino, proc);
14547                 fatal_error(ctx, 0);
14548         }
14549 }
14550
14551 extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
14552                                struct ext2_inode * inode, const char *proc)
14553 {
14554         int retval;
14555
14556         retval = ext2fs_write_inode(ctx->fs, ino, inode);
14557         if (retval) {
14558                 com_err("ext2fs_write_inode", retval,
14559                         _("while writing inode %ld in %s"), ino, proc);
14560                 fatal_error(ctx, 0);
14561         }
14562 }
14563
14564 #ifdef MTRACE
14565 void mtrace_print(char *mesg)
14566 {
14567         FILE    *malloc_get_mallstream();
14568         FILE    *f = malloc_get_mallstream();
14569
14570         if (f)
14571                 fprintf(f, "============= %s\n", mesg);
14572 }
14573 #endif
14574
14575 blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
14576                    io_manager manager)
14577 {
14578         struct ext2_super_block *sb;
14579         io_channel              io = NULL;
14580         void                    *buf = NULL;
14581         int                     blocksize;
14582         blk_t                   superblock, ret_sb = 8193;
14583
14584         if (fs && fs->super) {
14585                 ret_sb = (fs->super->s_blocks_per_group +
14586                           fs->super->s_first_data_block);
14587                 if (ctx) {
14588                         ctx->superblock = ret_sb;
14589                         ctx->blocksize = fs->blocksize;
14590                 }
14591                 return ret_sb;
14592         }
14593
14594         if (ctx) {
14595                 if (ctx->blocksize) {
14596                         ret_sb = ctx->blocksize * 8;
14597                         if (ctx->blocksize == 1024)
14598                                 ret_sb++;
14599                         ctx->superblock = ret_sb;
14600                         return ret_sb;
14601                 }
14602                 ctx->superblock = ret_sb;
14603                 ctx->blocksize = 1024;
14604         }
14605
14606         if (!name || !manager)
14607                 goto cleanup;
14608
14609         if (manager->open(name, 0, &io) != 0)
14610                 goto cleanup;
14611
14612         if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
14613                 goto cleanup;
14614         sb = (struct ext2_super_block *) buf;
14615
14616         for (blocksize = EXT2_MIN_BLOCK_SIZE;
14617              blocksize <= EXT2_MAX_BLOCK_SIZE ; blocksize *= 2) {
14618                 superblock = blocksize*8;
14619                 if (blocksize == 1024)
14620                         superblock++;
14621                 io_channel_set_blksize(io, blocksize);
14622                 if (io_channel_read_blk(io, superblock,
14623                                         -SUPERBLOCK_SIZE, buf))
14624                         continue;
14625 #ifdef EXT2FS_ENABLE_SWAPFS
14626                 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
14627                         ext2fs_swap_super(sb);
14628 #endif
14629                 if (sb->s_magic == EXT2_SUPER_MAGIC) {
14630                         ret_sb = superblock;
14631                         if (ctx) {
14632                                 ctx->superblock = superblock;
14633                                 ctx->blocksize = blocksize;
14634                         }
14635                         break;
14636                 }
14637         }
14638
14639 cleanup:
14640         if (io)
14641                 io_channel_close(io);
14642         if (buf)
14643                 ext2fs_free_mem(&buf);
14644         return (ret_sb);
14645 }
14646
14647
14648 /*
14649  * This function runs through the e2fsck passes and calls them all,
14650  * returning restart, abort, or cancel as necessary...
14651  */
14652 typedef void (*pass_t)(e2fsck_t ctx);
14653
14654 static const pass_t e2fsck_passes[] = {
14655         e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
14656         e2fsck_pass5, 0 };
14657
14658 #define E2F_FLAG_RUN_RETURN     (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
14659
14660 static int e2fsck_run(e2fsck_t ctx)
14661 {
14662         int     i;
14663         pass_t  e2fsck_pass;
14664
14665         if (setjmp(ctx->abort_loc)) {
14666                 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
14667                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
14668         }
14669         ctx->flags |= E2F_FLAG_SETJMP_OK;
14670
14671         for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
14672                 if (ctx->flags & E2F_FLAG_RUN_RETURN)
14673                         break;
14674                 e2fsck_pass(ctx);
14675                 if (ctx->progress)
14676                         (void) (ctx->progress)(ctx, 0, 0, 0);
14677         }
14678         ctx->flags &= ~E2F_FLAG_SETJMP_OK;
14679
14680         if (ctx->flags & E2F_FLAG_RUN_RETURN)
14681                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
14682         return 0;
14683 }
14684
14685
14686 /*
14687  * unix.c - The unix-specific code for e2fsck
14688  */
14689
14690
14691 /* Command line options */
14692 static int swapfs;
14693 #ifdef ENABLE_SWAPFS
14694 static int normalize_swapfs;
14695 #endif
14696 static int cflag;               /* check disk */
14697 static int show_version_only;
14698 static int verbose;
14699
14700 static int replace_bad_blocks;
14701 static int keep_bad_blocks;
14702 static char *bad_blocks_file;
14703
14704 #ifdef __CONFIG_JBD_DEBUG__E2FS         /* Enabled by configure --enable-jfs-debug */
14705 int journal_enable_debug = -1;
14706 #endif
14707
14708 #if 0
14709 static void usage(e2fsck_t ctx)
14710 {
14711         fprintf(stderr,
14712                 _("Usage: %s [-panyrcdfvstDFSV] [-b superblock] [-B blocksize]\n"
14713                 "\t\t[-I inode_buffer_blocks] [-P process_inode_size]\n"
14714                 "\t\t[-l|-L bad_blocks_file] [-C fd] [-j ext-journal]\n"
14715                 "\t\t[-E extended-options] device\n"),
14716                 ctx->program_name);
14717
14718         fprintf(stderr, _("\nEmergency help:\n"
14719                 " -p                   Automatic repair (no questions)\n"
14720                 " -n                   Make no changes to the filesystem\n"
14721                 " -y                   Assume \"yes\" to all questions\n"
14722                 " -c                   Check for bad blocks and add them to the badblock list\n"
14723                 " -f                   Force checking even if filesystem is marked clean\n"));
14724         fprintf(stderr, _(""
14725                 " -v                   Be verbose\n"
14726                 " -b superblock        Use alternative superblock\n"
14727                 " -B blocksize         Force blocksize when looking for superblock\n"
14728                 " -j external-journal  Set location of the external journal\n"
14729                 " -l bad_blocks_file   Add to badblocks list\n"
14730                 " -L bad_blocks_file   Set badblocks list\n"
14731                 ));
14732
14733         exit(EXIT_USAGE);
14734 }
14735 #endif
14736
14737 #define P_E2(singular, plural, n)       n, ((n) == 1 ? singular : plural)
14738
14739 static void show_stats(e2fsck_t ctx)
14740 {
14741         ext2_filsys fs = ctx->fs;
14742         int inodes, inodes_used, blocks, blocks_used;
14743         int dir_links;
14744         int num_files, num_links;
14745         int frag_percent;
14746
14747         dir_links = 2 * ctx->fs_directory_count - 1;
14748         num_files = ctx->fs_total_count - dir_links;
14749         num_links = ctx->fs_links_count - dir_links;
14750         inodes = fs->super->s_inodes_count;
14751         inodes_used = (fs->super->s_inodes_count -
14752                        fs->super->s_free_inodes_count);
14753         blocks = fs->super->s_blocks_count;
14754         blocks_used = (fs->super->s_blocks_count -
14755                        fs->super->s_free_blocks_count);
14756
14757         frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
14758         frag_percent = (frag_percent + 5) / 10;
14759
14760         if (!verbose) {
14761                 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
14762                        ctx->device_name, inodes_used, inodes,
14763                        frag_percent / 10, frag_percent % 10,
14764                        blocks_used, blocks);
14765                 return;
14766         }
14767         printf ("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
14768                 100 * inodes_used / inodes);
14769         printf ("%8d non-contiguous inode%s (%0d.%d%%)\n",
14770                 P_E2("", "s", ctx->fs_fragmented),
14771                 frag_percent / 10, frag_percent % 10);
14772         printf (_("         # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
14773                 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
14774         printf ("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
14775                 (int) ((long long) 100 * blocks_used / blocks));
14776         printf ("%8d bad block%s\n", P_E2("", "s", ctx->fs_badblocks_count));
14777         printf ("%8d large file%s\n", P_E2("", "s", ctx->large_files));
14778         printf ("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
14779         printf ("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
14780         printf ("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
14781         printf ("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
14782         printf ("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
14783         printf ("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
14784         printf ("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
14785         printf (" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
14786         printf ("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
14787         printf ("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
14788 }
14789
14790 static void check_mount(e2fsck_t ctx)
14791 {
14792         errcode_t       retval;
14793         int             cont;
14794
14795         retval = ext2fs_check_if_mounted(ctx->filesystem_name,
14796                                          &ctx->mount_flags);
14797         if (retval) {
14798                 com_err("ext2fs_check_if_mount", retval,
14799                         _("while determining whether %s is mounted."),
14800                         ctx->filesystem_name);
14801                 return;
14802         }
14803
14804         /*
14805          * If the filesystem isn't mounted, or it's the root filesystem
14806          * and it's mounted read-only, then everything's fine.
14807          */
14808         if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
14809             ((ctx->mount_flags & EXT2_MF_ISROOT) &&
14810              (ctx->mount_flags & EXT2_MF_READONLY)))
14811                 return;
14812
14813         if (ctx->options & E2F_OPT_READONLY) {
14814                 printf(_("Warning!  %s is mounted.\n"), ctx->filesystem_name);
14815                 return;
14816         }
14817
14818         printf(_("%s is mounted.  "), ctx->filesystem_name);
14819         if (!ctx->interactive)
14820                 fatal_error(ctx, _("Cannot continue, aborting.\n\n"));
14821         printf(_("\n\n\007\007\007\007WARNING!!!  "
14822                "Running e2fsck on a mounted filesystem may cause\n"
14823                "SEVERE filesystem damage.\007\007\007\n\n"));
14824         cont = ask_yn(_("Do you really want to continue"), -1);
14825         if (!cont) {
14826                 printf (_("check aborted.\n"));
14827                 exit (0);
14828         }
14829         return;
14830 }
14831
14832 static int is_on_batt(void)
14833 {
14834         FILE    *f;
14835         DIR     *d;
14836         char    tmp[80], tmp2[80], fname[80];
14837         unsigned int    acflag;
14838         struct dirent*  de;
14839
14840         f = fopen("/proc/apm", "r");
14841         if (f) {
14842                 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
14843                         acflag = 1;
14844                 fclose(f);
14845                 return (acflag != 1);
14846         }
14847         d = opendir("/proc/acpi/ac_adapter");
14848         if (d) {
14849                 while ((de=readdir(d)) != NULL) {
14850                         if (!strncmp(".", de->d_name, 1))
14851                                 continue;
14852                         snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
14853                                  de->d_name);
14854                         f = fopen(fname, "r");
14855                         if (!f)
14856                                 continue;
14857                         if (fscanf(f, "%s %s", tmp2, tmp) != 2)
14858                                 tmp[0] = 0;
14859                         fclose(f);
14860                         if (strncmp(tmp, "off-line", 8) == 0) {
14861                                 closedir(d);
14862                                 return 1;
14863                         }
14864                 }
14865                 closedir(d);
14866         }
14867         return 0;
14868 }
14869
14870 /*
14871  * This routine checks to see if a filesystem can be skipped; if so,
14872  * it will exit with EXIT_OK.  Under some conditions it will print a
14873  * message explaining why a check is being forced.
14874  */
14875 static void check_if_skip(e2fsck_t ctx)
14876 {
14877         ext2_filsys fs = ctx->fs;
14878         const char *reason = NULL;
14879         unsigned int reason_arg = 0;
14880         long next_check;
14881         int batt = is_on_batt();
14882         time_t now = time(0);
14883
14884         if ((ctx->options & E2F_OPT_FORCE) || bad_blocks_file ||
14885             cflag || swapfs)
14886                 return;
14887
14888         if ((fs->super->s_state & EXT2_ERROR_FS) ||
14889             !ext2fs_test_valid(fs))
14890                 reason = _(" contains a file system with errors");
14891         else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
14892                 reason = _(" was not cleanly unmounted");
14893         else if ((fs->super->s_max_mnt_count > 0) &&
14894                  (fs->super->s_mnt_count >=
14895                   (unsigned) fs->super->s_max_mnt_count)) {
14896                 reason = _(" has been mounted %u times without being checked");
14897                 reason_arg = fs->super->s_mnt_count;
14898                 if (batt && (fs->super->s_mnt_count <
14899                              (unsigned) fs->super->s_max_mnt_count*2))
14900                         reason = 0;
14901         } else if (fs->super->s_checkinterval &&
14902                    ((now - fs->super->s_lastcheck) >=
14903                     fs->super->s_checkinterval)) {
14904                 reason = _(" has gone %u days without being checked");
14905                 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
14906                 if (batt && ((now - fs->super->s_lastcheck) <
14907                              fs->super->s_checkinterval*2))
14908                         reason = 0;
14909         }
14910         if (reason) {
14911                 fputs(ctx->device_name, stdout);
14912                 printf(reason, reason_arg);
14913                 fputs(_(", check forced.\n"), stdout);
14914                 return;
14915         }
14916         printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
14917                fs->super->s_inodes_count - fs->super->s_free_inodes_count,
14918                fs->super->s_inodes_count,
14919                fs->super->s_blocks_count - fs->super->s_free_blocks_count,
14920                fs->super->s_blocks_count);
14921         next_check = 100000;
14922         if (fs->super->s_max_mnt_count > 0) {
14923                 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
14924                 if (next_check <= 0)
14925                         next_check = 1;
14926         }
14927         if (fs->super->s_checkinterval &&
14928             ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
14929                 next_check = 1;
14930         if (next_check <= 5) {
14931                 if (next_check == 1)
14932                         fputs(_(" (check after next mount)"), stdout);
14933                 else
14934                         printf(_(" (check in %ld mounts)"), next_check);
14935         }
14936         fputc('\n', stdout);
14937         ext2fs_close(fs);
14938         ctx->fs = NULL;
14939         e2fsck_free_context(ctx);
14940         exit(EXIT_OK);
14941 }
14942
14943 /*
14944  * For completion notice
14945  */
14946 struct percent_tbl {
14947         int     max_pass;
14948         int     table[32];
14949 };
14950 static const struct percent_tbl e2fsck_tbl = {
14951         5, { 0, 70, 90, 92,  95, 100 }
14952 };
14953
14954 static char bar[128], spaces[128];
14955
14956 static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
14957                           int max)
14958 {
14959         float   percent;
14960
14961         if (pass <= 0)
14962                 return 0.0;
14963         if (pass > tbl->max_pass || max == 0)
14964                 return 100.0;
14965         percent = ((float) curr) / ((float) max);
14966         return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
14967                 + tbl->table[pass-1]);
14968 }
14969
14970 extern void e2fsck_clear_progbar(e2fsck_t ctx)
14971 {
14972         if (!(ctx->flags & E2F_FLAG_PROG_BAR))
14973                 return;
14974
14975         printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
14976                ctx->stop_meta);
14977         fflush(stdout);
14978         ctx->flags &= ~E2F_FLAG_PROG_BAR;
14979 }
14980
14981 int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
14982                            unsigned int dpynum)
14983 {
14984         static const char spinner[] = "\\|/-";
14985         int     i;
14986         unsigned int    tick;
14987         struct timeval  tv;
14988         int dpywidth;
14989         int fixed_percent;
14990
14991         if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
14992                 return 0;
14993
14994         /*
14995          * Calculate the new progress position.  If the
14996          * percentage hasn't changed, then we skip out right
14997          * away.
14998          */
14999         fixed_percent = (int) ((10 * percent) + 0.5);
15000         if (ctx->progress_last_percent == fixed_percent)
15001                 return 0;
15002         ctx->progress_last_percent = fixed_percent;
15003
15004         /*
15005          * If we've already updated the spinner once within
15006          * the last 1/8th of a second, no point doing it
15007          * again.
15008          */
15009         gettimeofday(&tv, NULL);
15010         tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
15011         if ((tick == ctx->progress_last_time) &&
15012             (fixed_percent != 0) && (fixed_percent != 1000))
15013                 return 0;
15014         ctx->progress_last_time = tick;
15015
15016         /*
15017          * Advance the spinner, and note that the progress bar
15018          * will be on the screen
15019          */
15020         ctx->progress_pos = (ctx->progress_pos+1) & 3;
15021         ctx->flags |= E2F_FLAG_PROG_BAR;
15022
15023         dpywidth = 66 - strlen(label);
15024         dpywidth = 8 * (dpywidth / 8);
15025         if (dpynum)
15026                 dpywidth -= 8;
15027
15028         i = ((percent * dpywidth) + 50) / 100;
15029         printf("%s%s: |%s%s", ctx->start_meta, label,
15030                bar + (sizeof(bar) - (i+1)),
15031                spaces + (sizeof(spaces) - (dpywidth - i + 1)));
15032         if (fixed_percent == 1000)
15033                 fputc('|', stdout);
15034         else
15035                 fputc(spinner[ctx->progress_pos & 3], stdout);
15036         printf(" %4.1f%%  ", percent);
15037         if (dpynum)
15038                 printf("%u\r", dpynum);
15039         else
15040                 fputs(" \r", stdout);
15041         fputs(ctx->stop_meta, stdout);
15042
15043         if (fixed_percent == 1000)
15044                 e2fsck_clear_progbar(ctx);
15045         fflush(stdout);
15046
15047         return 0;
15048 }
15049
15050 static int e2fsck_update_progress(e2fsck_t ctx, int pass,
15051                                   unsigned long cur, unsigned long max)
15052 {
15053         char buf[80];
15054         float percent;
15055
15056         if (pass == 0)
15057                 return 0;
15058
15059         if (ctx->progress_fd) {
15060                 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
15061                 write(ctx->progress_fd, buf, strlen(buf));
15062         } else {
15063                 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
15064                 e2fsck_simple_progress(ctx, ctx->device_name,
15065                                        percent, 0);
15066         }
15067         return 0;
15068 }
15069
15070 static void reserve_stdio_fds(void)
15071 {
15072         int     fd;
15073
15074         while (1) {
15075                 fd = open(bb_dev_null, O_RDWR);
15076                 if (fd > 2)
15077                         break;
15078                 if (fd < 0) {
15079                         fprintf(stderr, _("ERROR: Couldn't open "
15080                                 "/dev/null (%s)\n"),
15081                                 strerror(errno));
15082                         break;
15083                 }
15084         }
15085         close(fd);
15086 }
15087
15088 static void signal_progress_on(int sig FSCK_ATTR((unused)))
15089 {
15090         e2fsck_t ctx = e2fsck_global_ctx;
15091
15092         if (!ctx)
15093                 return;
15094
15095         ctx->progress = e2fsck_update_progress;
15096         ctx->progress_fd = 0;
15097 }
15098
15099 static void signal_progress_off(int sig FSCK_ATTR((unused)))
15100 {
15101         e2fsck_t ctx = e2fsck_global_ctx;
15102
15103         if (!ctx)
15104                 return;
15105
15106         e2fsck_clear_progbar(ctx);
15107         ctx->progress = 0;
15108 }
15109
15110 static void signal_cancel(int sig FSCK_ATTR((unused)))
15111 {
15112         e2fsck_t ctx = e2fsck_global_ctx;
15113
15114         if (!ctx)
15115                 exit(FSCK_CANCELED);
15116
15117         ctx->flags |= E2F_FLAG_CANCEL;
15118 }
15119
15120 static void parse_extended_opts(e2fsck_t ctx, const char *opts)
15121 {
15122         char    *buf, *token, *next, *p, *arg;
15123         int     ea_ver;
15124         int     extended_usage = 0;
15125
15126         buf = string_copy(opts, 0);
15127         for (token = buf; token && *token; token = next) {
15128                 p = strchr(token, ',');
15129                 next = 0;
15130                 if (p) {
15131                         *p = 0;
15132                         next = p+1;
15133                 }
15134                 arg = strchr(token, '=');
15135                 if (arg) {
15136                         *arg = 0;
15137                         arg++;
15138                 }
15139                 if (strcmp(token, "ea_ver") == 0) {
15140                         if (!arg) {
15141                                 extended_usage++;
15142                                 continue;
15143                         }
15144                         ea_ver = strtoul(arg, &p, 0);
15145                         if (*p ||
15146                             ((ea_ver != 1) && (ea_ver != 2))) {
15147                                 fprintf(stderr,
15148                                         _("Invalid EA version.\n"));
15149                                 extended_usage++;
15150                                 continue;
15151                         }
15152                         ctx->ext_attr_ver = ea_ver;
15153                 } else
15154                         extended_usage++;
15155         }
15156         if (extended_usage) {
15157                 bb_error_msg_and_die(
15158                         "Extended options are separated by commas, "
15159                         "and may take an argument which\n"
15160                         "is set off by an equals ('=') sign.  "
15161                         "Valid raid options are:\n"
15162                         "\tea_ver=<ea_version (1 or 2)\n\n");
15163         }
15164 }
15165
15166
15167 static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
15168 {
15169         int             flush = 0;
15170         int             c, fd;
15171 #ifdef MTRACE
15172         extern void     *mallwatch;
15173 #endif
15174         e2fsck_t        ctx;
15175         errcode_t       retval;
15176         struct sigaction        sa;
15177         char            *extended_opts = 0;
15178
15179         retval = e2fsck_allocate_context(&ctx);
15180         if (retval)
15181                 return retval;
15182
15183         *ret_ctx = ctx;
15184
15185         setvbuf(stdout, NULL, _IONBF, BUFSIZ);
15186         setvbuf(stderr, NULL, _IONBF, BUFSIZ);
15187         if (isatty(0) && isatty(1)) {
15188                 ctx->interactive = 1;
15189         } else {
15190                 ctx->start_meta[0] = '\001';
15191                 ctx->stop_meta[0] = '\002';
15192         }
15193         memset(bar, '=', sizeof(bar)-1);
15194         memset(spaces, ' ', sizeof(spaces)-1);
15195         blkid_get_cache(&ctx->blkid, NULL);
15196
15197         if (argc && *argv)
15198                 ctx->program_name = *argv;
15199         else
15200                 ctx->program_name = "e2fsck";
15201         while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
15202                 switch (c) {
15203                 case 'C':
15204                         ctx->progress = e2fsck_update_progress;
15205                         ctx->progress_fd = atoi(optarg);
15206                         if (!ctx->progress_fd)
15207                                 break;
15208                         /* Validate the file descriptor to avoid disasters */
15209                         fd = dup(ctx->progress_fd);
15210                         if (fd < 0) {
15211                                 fprintf(stderr,
15212                                 _("Error validating file descriptor %d: %s\n"),
15213                                         ctx->progress_fd,
15214                                         error_message(errno));
15215                                 fatal_error(ctx,
15216                         _("Invalid completion information file descriptor"));
15217                         } else
15218                                 close(fd);
15219                         break;
15220                 case 'D':
15221                         ctx->options |= E2F_OPT_COMPRESS_DIRS;
15222                         break;
15223                 case 'E':
15224                         extended_opts = optarg;
15225                         break;
15226                 case 'p':
15227                 case 'a':
15228                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
15229                         conflict_opt:
15230                                 fatal_error(ctx,
15231         _("Only one the options -p/-a, -n or -y may be specified."));
15232                         }
15233                         ctx->options |= E2F_OPT_PREEN;
15234                         break;
15235                 case 'n':
15236                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
15237                                 goto conflict_opt;
15238                         ctx->options |= E2F_OPT_NO;
15239                         break;
15240                 case 'y':
15241                         if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
15242                                 goto conflict_opt;
15243                         ctx->options |= E2F_OPT_YES;
15244                         break;
15245                 case 't':
15246 #ifdef RESOURCE_TRACK
15247                         if (ctx->options & E2F_OPT_TIME)
15248                                 ctx->options |= E2F_OPT_TIME2;
15249                         else
15250                                 ctx->options |= E2F_OPT_TIME;
15251 #else
15252                         fprintf(stderr, _("The -t option is not "
15253                                 "supported on this version of e2fsck.\n"));
15254 #endif
15255                         break;
15256                 case 'c':
15257                         if (cflag++)
15258                                 ctx->options |= E2F_OPT_WRITECHECK;
15259                         ctx->options |= E2F_OPT_CHECKBLOCKS;
15260                         break;
15261                 case 'r':
15262                         /* What we do by default, anyway! */
15263                         break;
15264                 case 'b':
15265                         ctx->use_superblock = atoi(optarg);
15266                         ctx->flags |= E2F_FLAG_SB_SPECIFIED;
15267                         break;
15268                 case 'B':
15269                         ctx->blocksize = atoi(optarg);
15270                         break;
15271                 case 'I':
15272                         ctx->inode_buffer_blocks = atoi(optarg);
15273                         break;
15274                 case 'j':
15275                         ctx->journal_name = string_copy(optarg, 0);
15276                         break;
15277                 case 'P':
15278                         ctx->process_inode_size = atoi(optarg);
15279                         break;
15280                 case 'L':
15281                         replace_bad_blocks++;
15282                 case 'l':
15283                         bad_blocks_file = string_copy(optarg, 0);
15284                         break;
15285                 case 'd':
15286                         ctx->options |= E2F_OPT_DEBUG;
15287                         break;
15288                 case 'f':
15289                         ctx->options |= E2F_OPT_FORCE;
15290                         break;
15291                 case 'F':
15292                         flush = 1;
15293                         break;
15294                 case 'v':
15295                         verbose = 1;
15296                         break;
15297                 case 'V':
15298                         show_version_only = 1;
15299                         break;
15300 #ifdef MTRACE
15301                 case 'M':
15302                         mallwatch = (void *) strtol(optarg, NULL, 0);
15303                         break;
15304 #endif
15305                 case 'N':
15306                         ctx->device_name = optarg;
15307                         break;
15308 #ifdef ENABLE_SWAPFS
15309                 case 's':
15310                         normalize_swapfs = 1;
15311                 case 'S':
15312                         swapfs = 1;
15313                         break;
15314 #else
15315                 case 's':
15316                 case 'S':
15317                         fprintf(stderr, _("Byte-swapping filesystems "
15318                                           "not compiled in this version "
15319                                           "of e2fsck\n"));
15320                         exit(1);
15321 #endif
15322                 case 'k':
15323                         keep_bad_blocks++;
15324                         break;
15325                 default:
15326                         usage();
15327                 }
15328         if (show_version_only)
15329                 return 0;
15330         if (optind != argc - 1)
15331                 usage();
15332         if ((ctx->options & E2F_OPT_NO) && !bad_blocks_file &&
15333             !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
15334                 ctx->options |= E2F_OPT_READONLY;
15335         ctx->io_options = strchr(argv[optind], '?');
15336         if (ctx->io_options)
15337                 *ctx->io_options++ = 0;
15338         ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
15339         if (!ctx->filesystem_name) {
15340                 com_err(ctx->program_name, 0, _("Unable to resolve '%s'"),
15341                         argv[optind]);
15342                 fatal_error(ctx, 0);
15343         }
15344         if (extended_opts)
15345                 parse_extended_opts(ctx, extended_opts);
15346
15347         if (flush) {
15348                 fd = open(ctx->filesystem_name, O_RDONLY, 0);
15349                 if (fd < 0) {
15350                         com_err("open", errno,
15351                                 _("while opening %s for flushing"),
15352                                 ctx->filesystem_name);
15353                         fatal_error(ctx, 0);
15354                 }
15355                 if ((retval = ext2fs_sync_device(fd, 1))) {
15356                         com_err("ext2fs_sync_device", retval,
15357                                 _("while trying to flush %s"),
15358                                 ctx->filesystem_name);
15359                         fatal_error(ctx, 0);
15360                 }
15361                 close(fd);
15362         }
15363 #ifdef ENABLE_SWAPFS
15364         if (swapfs) {
15365                 if (cflag || bad_blocks_file) {
15366                         fprintf(stderr, _("Incompatible options not "
15367                                           "allowed when byte-swapping.\n"));
15368                         exit(EXIT_USAGE);
15369                 }
15370         }
15371 #endif
15372         if (cflag && bad_blocks_file) {
15373                 fprintf(stderr, _("The -c and the -l/-L options may "
15374                                   "not be both used at the same time.\n"));
15375                 exit(EXIT_USAGE);
15376         }
15377         /*
15378          * Set up signal action
15379          */
15380         memset(&sa, 0, sizeof(struct sigaction));
15381         sa.sa_handler = signal_cancel;
15382         sigaction(SIGINT, &sa, 0);
15383         sigaction(SIGTERM, &sa, 0);
15384 #ifdef SA_RESTART
15385         sa.sa_flags = SA_RESTART;
15386 #endif
15387         e2fsck_global_ctx = ctx;
15388         sa.sa_handler = signal_progress_on;
15389         sigaction(SIGUSR1, &sa, 0);
15390         sa.sa_handler = signal_progress_off;
15391         sigaction(SIGUSR2, &sa, 0);
15392
15393         /* Update our PATH to include /sbin if we need to run badblocks  */
15394         if (cflag)
15395                 e2fs_set_sbin_path();
15396 #ifdef __CONFIG_JBD_DEBUG__E2FS
15397         if (getenv("E2FSCK_JBD_DEBUG"))
15398                 journal_enable_debug = atoi(getenv("E2FSCK_JBD_DEBUG"));
15399 #endif
15400         return 0;
15401 }
15402
15403 static const char my_ver_string[] = E2FSPROGS_VERSION;
15404 static const char my_ver_date[] = E2FSPROGS_DATE;
15405
15406 int e2fsck_main (int argc, char *argv[])
15407 {
15408         errcode_t       retval;
15409         int             exit_value = EXIT_OK;
15410         ext2_filsys     fs = 0;
15411         io_manager      io_ptr;
15412         struct ext2_super_block *sb;
15413         const char      *lib_ver_date;
15414         int             my_ver, lib_ver;
15415         e2fsck_t        ctx;
15416         struct problem_context pctx;
15417         int flags, run_result;
15418
15419         clear_problem_context(&pctx);
15420 #ifdef MTRACE
15421         mtrace();
15422 #endif
15423 #ifdef MCHECK
15424         mcheck(0);
15425 #endif
15426 #ifdef ENABLE_NLS
15427         setlocale(LC_MESSAGES, "");
15428         setlocale(LC_CTYPE, "");
15429         bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
15430         textdomain(NLS_CAT_NAME);
15431 #endif
15432         my_ver = ext2fs_parse_version_string(my_ver_string);
15433         lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
15434         if (my_ver > lib_ver) {
15435                 fprintf( stderr, _("Error: ext2fs library version "
15436                         "out of date!\n"));
15437                 show_version_only++;
15438         }
15439
15440         retval = PRS(argc, argv, &ctx);
15441         if (retval) {
15442                 com_err("e2fsck", retval,
15443                         _("while trying to initialize program"));
15444                 exit(EXIT_ERROR);
15445         }
15446         reserve_stdio_fds();
15447
15448 #ifdef RESOURCE_TRACK
15449         init_resource_track(&ctx->global_rtrack);
15450 #endif
15451
15452         if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
15453                 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
15454                          my_ver_date);
15455
15456         if (show_version_only) {
15457                 fprintf(stderr, _("\tUsing %s, %s\n"),
15458                         error_message(EXT2_ET_BASE), lib_ver_date);
15459                 exit(EXIT_OK);
15460         }
15461
15462         check_mount(ctx);
15463
15464         if (!(ctx->options & E2F_OPT_PREEN) &&
15465             !(ctx->options & E2F_OPT_NO) &&
15466             !(ctx->options & E2F_OPT_YES)) {
15467                 if (!ctx->interactive)
15468                         fatal_error(ctx,
15469                                     _("need terminal for interactive repairs"));
15470         }
15471         ctx->superblock = ctx->use_superblock;
15472 restart:
15473 #ifdef CONFIG_TESTIO_DEBUG
15474         io_ptr = test_io_manager;
15475         test_io_backing_manager = unix_io_manager;
15476 #else
15477         io_ptr = unix_io_manager;
15478 #endif
15479         flags = 0;
15480         if ((ctx->options & E2F_OPT_READONLY) == 0)
15481                 flags |= EXT2_FLAG_RW;
15482
15483         if (ctx->superblock && ctx->blocksize) {
15484                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
15485                                       flags, ctx->superblock, ctx->blocksize,
15486                                       io_ptr, &fs);
15487         } else if (ctx->superblock) {
15488                 int blocksize;
15489                 for (blocksize = EXT2_MIN_BLOCK_SIZE;
15490                      blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
15491                         retval = ext2fs_open2(ctx->filesystem_name,
15492                                               ctx->io_options, flags,
15493                                               ctx->superblock, blocksize,
15494                                               io_ptr, &fs);
15495                         if (!retval)
15496                                 break;
15497                 }
15498         } else
15499                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
15500                                       flags, 0, 0, io_ptr, &fs);
15501         if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
15502             !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
15503             ((retval == EXT2_ET_BAD_MAGIC) ||
15504              ((retval == 0) && ext2fs_check_desc(fs)))) {
15505                 if (!fs || (fs->group_desc_count > 1)) {
15506                         printf(_("%s trying backup blocks...\n"),
15507                                retval ? _("Couldn't find ext2 superblock,") :
15508                                _("Group descriptors look bad..."));
15509                         get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
15510                         if (fs)
15511                                 ext2fs_close(fs);
15512                         goto restart;
15513                 }
15514         }
15515         if (retval) {
15516                 com_err(ctx->program_name, retval, _("while trying to open %s"),
15517                         ctx->filesystem_name);
15518                 if (retval == EXT2_ET_REV_TOO_HIGH) {
15519                         printf(_("The filesystem revision is apparently "
15520                                "too high for this version of e2fsck.\n"
15521                                "(Or the filesystem superblock "
15522                                "is corrupt)\n\n"));
15523                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
15524                 } else if (retval == EXT2_ET_SHORT_READ)
15525                         printf(_("Could this be a zero-length partition?\n"));
15526                 else if ((retval == EPERM) || (retval == EACCES))
15527                         printf(_("You must have %s access to the "
15528                                "filesystem or be root\n"),
15529                                (ctx->options & E2F_OPT_READONLY) ?
15530                                "r/o" : "r/w");
15531                 else if (retval == ENXIO)
15532                         printf(_("Possibly non-existent or swap device?\n"));
15533 #ifdef EROFS
15534                 else if (retval == EROFS)
15535                         printf(_("Disk write-protected; use the -n option "
15536                                "to do a read-only\n"
15537                                "check of the device.\n"));
15538 #endif
15539                 else
15540                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
15541                 fatal_error(ctx, 0);
15542         }
15543         ctx->fs = fs;
15544         fs->priv_data = ctx;
15545         sb = fs->super;
15546         if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
15547                 com_err(ctx->program_name, EXT2_ET_REV_TOO_HIGH,
15548                         _("while trying to open %s"),
15549                         ctx->filesystem_name);
15550         get_newer:
15551                 fatal_error(ctx, _("Get a newer version of e2fsck!"));
15552         }
15553
15554         /*
15555          * Set the device name, which is used whenever we print error
15556          * or informational messages to the user.
15557          */
15558         if (ctx->device_name == 0 &&
15559             (sb->s_volume_name[0] != 0)) {
15560                 ctx->device_name = string_copy(sb->s_volume_name,
15561                                                sizeof(sb->s_volume_name));
15562         }
15563         if (ctx->device_name == 0)
15564                 ctx->device_name = ctx->filesystem_name;
15565
15566         /*
15567          * Make sure the ext3 superblock fields are consistent.
15568          */
15569         retval = e2fsck_check_ext3_journal(ctx);
15570         if (retval) {
15571                 com_err(ctx->program_name, retval,
15572                         _("while checking ext3 journal for %s"),
15573                         ctx->device_name);
15574                 fatal_error(ctx, 0);
15575         }
15576
15577         /*
15578          * Check to see if we need to do ext3-style recovery.  If so,
15579          * do it, and then restart the fsck.
15580          */
15581         if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
15582                 if (ctx->options & E2F_OPT_READONLY) {
15583                         printf(_("Warning: skipping journal recovery "
15584                                  "because doing a read-only filesystem "
15585                                  "check.\n"));
15586                         io_channel_flush(ctx->fs->io);
15587                 } else {
15588                         if (ctx->flags & E2F_FLAG_RESTARTED) {
15589                                 /*
15590                                  * Whoops, we attempted to run the
15591                                  * journal twice.  This should never
15592                                  * happen, unless the hardware or
15593                                  * device driver is being bogus.
15594                                  */
15595                                 com_err(ctx->program_name, 0,
15596                                         _("unable to set superblock flags on %s\n"), ctx->device_name);
15597                                 fatal_error(ctx, 0);
15598                         }
15599                         retval = e2fsck_run_ext3_journal(ctx);
15600                         if (retval) {
15601                                 com_err(ctx->program_name, retval,
15602                                 _("while recovering ext3 journal of %s"),
15603                                         ctx->device_name);
15604                                 fatal_error(ctx, 0);
15605                         }
15606                         ext2fs_close(ctx->fs);
15607                         ctx->fs = 0;
15608                         ctx->flags |= E2F_FLAG_RESTARTED;
15609                         goto restart;
15610                 }
15611         }
15612
15613         /*
15614          * Check for compatibility with the feature sets.  We need to
15615          * be more stringent than ext2fs_open().
15616          */
15617         if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
15618             (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
15619                 com_err(ctx->program_name, EXT2_ET_UNSUPP_FEATURE,
15620                         "(%s)", ctx->device_name);
15621                 goto get_newer;
15622         }
15623         if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
15624                 com_err(ctx->program_name, EXT2_ET_RO_UNSUPP_FEATURE,
15625                         "(%s)", ctx->device_name);
15626                 goto get_newer;
15627         }
15628 #ifdef ENABLE_COMPRESSION
15629         if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
15630                 com_err(ctx->program_name, 0,
15631                         _("Warning: compression support is experimental.\n"));
15632 #endif
15633 #ifndef ENABLE_HTREE
15634         if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
15635                 com_err(ctx->program_name, 0,
15636                         _("E2fsck not compiled with HTREE support,\n\t"
15637                           "but filesystem %s has HTREE directories.\n"),
15638                         ctx->device_name);
15639                 goto get_newer;
15640         }
15641 #endif
15642
15643         /*
15644          * If the user specified a specific superblock, presumably the
15645          * master superblock has been trashed.  So we mark the
15646          * superblock as dirty, so it can be written out.
15647          */
15648         if (ctx->superblock &&
15649             !(ctx->options & E2F_OPT_READONLY))
15650                 ext2fs_mark_super_dirty(fs);
15651
15652         /*
15653          * We only update the master superblock because (a) paranoia;
15654          * we don't want to corrupt the backup superblocks, and (b) we
15655          * don't need to update the mount count and last checked
15656          * fields in the backup superblock (the kernel doesn't
15657          * update the backup superblocks anyway).
15658          */
15659         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
15660
15661         ehandler_init(fs->io);
15662
15663         if (ctx->superblock)
15664                 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
15665         ext2fs_mark_valid(fs);
15666         check_super_block(ctx);
15667         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15668                 fatal_error(ctx, 0);
15669         check_if_skip(ctx);
15670         if (bad_blocks_file)
15671                 read_bad_blocks_file(ctx, bad_blocks_file, replace_bad_blocks);
15672         else if (cflag)
15673                 read_bad_blocks_file(ctx, 0, !keep_bad_blocks); /* Test disk */
15674         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15675                 fatal_error(ctx, 0);
15676 #ifdef ENABLE_SWAPFS
15677
15678 #ifdef WORDS_BIGENDIAN
15679 #define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
15680 #else
15681 #define NATIVE_FLAG 0
15682 #endif
15683
15684
15685         if (normalize_swapfs) {
15686                 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
15687                         fprintf(stderr, _("%s: Filesystem byte order "
15688                                 "already normalized.\n"), ctx->device_name);
15689                         fatal_error(ctx, 0);
15690                 }
15691         }
15692         if (swapfs) {
15693                 swap_filesys(ctx);
15694                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15695                         fatal_error(ctx, 0);
15696         }
15697 #endif
15698
15699         /*
15700          * Mark the system as valid, 'til proven otherwise
15701          */
15702         ext2fs_mark_valid(fs);
15703
15704         retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
15705         if (retval) {
15706                 com_err(ctx->program_name, retval,
15707                         _("while reading bad blocks inode"));
15708                 preenhalt(ctx);
15709                 printf(_("This doesn't bode well,"
15710                          " but we'll try to go on...\n"));
15711         }
15712
15713         run_result = e2fsck_run(ctx);
15714         e2fsck_clear_progbar(ctx);
15715         if (run_result == E2F_FLAG_RESTART) {
15716                 printf(_("Restarting e2fsck from the beginning...\n"));
15717                 retval = e2fsck_reset_context(ctx);
15718                 if (retval) {
15719                         com_err(ctx->program_name, retval,
15720                                 _("while resetting context"));
15721                         fatal_error(ctx, 0);
15722                 }
15723                 ext2fs_close(fs);
15724                 goto restart;
15725         }
15726         if (run_result & E2F_FLAG_CANCEL) {
15727                 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
15728                        ctx->device_name : ctx->filesystem_name);
15729                 exit_value |= FSCK_CANCELED;
15730         }
15731         if (run_result & E2F_FLAG_ABORT)
15732                 fatal_error(ctx, _("aborted"));
15733
15734 #ifdef MTRACE
15735         mtrace_print("Cleanup");
15736 #endif
15737         if (ext2fs_test_changed(fs)) {
15738                 exit_value |= EXIT_NONDESTRUCT;
15739                 if (!(ctx->options & E2F_OPT_PREEN))
15740                     printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
15741                                ctx->device_name);
15742                 if (ctx->mount_flags & EXT2_MF_ISROOT) {
15743                         printf(_("%s: ***** REBOOT LINUX *****\n"),
15744                                ctx->device_name);
15745                         exit_value |= EXIT_DESTRUCT;
15746                 }
15747         }
15748         if (!ext2fs_test_valid(fs)) {
15749                 printf(_("\n%s: ********** WARNING: Filesystem still has "
15750                          "errors **********\n\n"), ctx->device_name);
15751                 exit_value |= EXIT_UNCORRECTED;
15752                 exit_value &= ~EXIT_NONDESTRUCT;
15753         }
15754         if (exit_value & FSCK_CANCELED)
15755                 exit_value &= ~EXIT_NONDESTRUCT;
15756         else {
15757                 show_stats(ctx);
15758                 if (!(ctx->options & E2F_OPT_READONLY)) {
15759                         if (ext2fs_test_valid(fs)) {
15760                                 if (!(sb->s_state & EXT2_VALID_FS))
15761                                         exit_value |= EXIT_NONDESTRUCT;
15762                                 sb->s_state = EXT2_VALID_FS;
15763                         } else
15764                                 sb->s_state &= ~EXT2_VALID_FS;
15765                         sb->s_mnt_count = 0;
15766                         sb->s_lastcheck = time(NULL);
15767                         ext2fs_mark_super_dirty(fs);
15768                 }
15769         }
15770
15771         e2fsck_write_bitmaps(ctx);
15772
15773         ext2fs_close(fs);
15774         ctx->fs = NULL;
15775         free(ctx->filesystem_name);
15776         free(ctx->journal_name);
15777         e2fsck_free_context(ctx);
15778
15779 #ifdef RESOURCE_TRACK
15780         if (ctx->options & E2F_OPT_TIME)
15781                 print_resource_track(NULL, &ctx->global_rtrack);
15782 #endif
15783
15784         return exit_value;
15785 }