fc7e740ace29e85518a557cf7ec15a5da3641dd6
[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  * Exit codes used by fsck-type programs
83  */
84 #define FSCK_OK          0      /* No errors */
85 #define FSCK_NONDESTRUCT 1      /* File system errors corrected */
86 #define FSCK_REBOOT      2      /* System should be rebooted */
87 #define FSCK_UNCORRECTED 4      /* File system errors left uncorrected */
88 #define FSCK_ERROR       8      /* Operational error */
89 #define FSCK_USAGE       16     /* Usage or syntax error */
90 #define FSCK_CANCELED    32     /* Aborted with a signal or ^C */
91 #define FSCK_LIBRARY     128    /* Shared library error */
92
93 /*
94  * The last ext2fs revision level that this version of e2fsck is able to
95  * support
96  */
97 #define E2FSCK_CURRENT_REV      1
98
99 /*
100  * The directory information structure; stores directory information
101  * collected in earlier passes, to avoid disk i/o in fetching the
102  * directory information.
103  */
104 struct dir_info {
105         ext2_ino_t              ino;    /* Inode number */
106         ext2_ino_t              dotdot; /* Parent according to '..' */
107         ext2_ino_t              parent; /* Parent according to treewalk */
108 };
109
110
111 /*
112  * The indexed directory information structure; stores information for
113  * directories which contain a hash tree index.
114  */
115 struct dx_dir_info {
116         ext2_ino_t              ino;            /* Inode number */
117         int                     numblocks;      /* number of blocks */
118         int                     hashversion;
119         short                   depth;          /* depth of tree */
120         struct dx_dirblock_info *dx_block;      /* Array of size numblocks */
121 };
122
123 #define DX_DIRBLOCK_ROOT        1
124 #define DX_DIRBLOCK_LEAF        2
125 #define DX_DIRBLOCK_NODE        3
126 #define DX_DIRBLOCK_CORRUPT     4
127 #define DX_DIRBLOCK_CLEARED     8
128
129 struct dx_dirblock_info {
130         int             type;
131         blk_t           phys;
132         int             flags;
133         blk_t           parent;
134         ext2_dirhash_t  min_hash;
135         ext2_dirhash_t  max_hash;
136         ext2_dirhash_t  node_min_hash;
137         ext2_dirhash_t  node_max_hash;
138 };
139
140 #define DX_FLAG_REFERENCED      1
141 #define DX_FLAG_DUP_REF         2
142 #define DX_FLAG_FIRST           4
143 #define DX_FLAG_LAST            8
144
145 #ifdef RESOURCE_TRACK
146 /*
147  * This structure is used for keeping track of how much resources have
148  * been used for a particular pass of e2fsck.
149  */
150 struct resource_track {
151         struct timeval time_start;
152         struct timeval user_start;
153         struct timeval system_start;
154         void    *brk_start;
155 };
156 #endif
157
158 /*
159  * E2fsck options
160  */
161 #define E2F_OPT_READONLY        0x0001
162 #define E2F_OPT_PREEN           0x0002
163 #define E2F_OPT_YES             0x0004
164 #define E2F_OPT_NO              0x0008
165 #define E2F_OPT_TIME            0x0010
166 #define E2F_OPT_TIME2           0x0020
167 #define E2F_OPT_CHECKBLOCKS     0x0040
168 #define E2F_OPT_DEBUG           0x0080
169 #define E2F_OPT_FORCE           0x0100
170 #define E2F_OPT_WRITECHECK      0x0200
171 #define E2F_OPT_COMPRESS_DIRS   0x0400
172
173 /*
174  * E2fsck flags
175  */
176 #define E2F_FLAG_ABORT          0x0001 /* Abort signaled */
177 #define E2F_FLAG_CANCEL         0x0002 /* Cancel signaled */
178 #define E2F_FLAG_SIGNAL_MASK    0x0003
179 #define E2F_FLAG_RESTART        0x0004 /* Restart signaled */
180
181 #define E2F_FLAG_SETJMP_OK      0x0010 /* Setjmp valid for abort */
182
183 #define E2F_FLAG_PROG_BAR       0x0020 /* Progress bar on screen */
184 #define E2F_FLAG_PROG_SUPPRESS  0x0040 /* Progress suspended */
185 #define E2F_FLAG_JOURNAL_INODE  0x0080 /* Create a new ext3 journal inode */
186 #define E2F_FLAG_SB_SPECIFIED   0x0100 /* The superblock was explicitly
187                                         * specified by the user */
188 #define E2F_FLAG_RESTARTED      0x0200 /* E2fsck has been restarted */
189 #define E2F_FLAG_RESIZE_INODE   0x0400 /* Request to recreate resize inode */
190
191 /*
192  * Defines for indicating the e2fsck pass number
193  */
194 #define E2F_PASS_1      1
195 #define E2F_PASS_2      2
196 #define E2F_PASS_3      3
197 #define E2F_PASS_4      4
198 #define E2F_PASS_5      5
199 #define E2F_PASS_1B     6
200
201
202 /*
203  * This is the global e2fsck structure.
204  */
205 typedef struct e2fsck_struct *e2fsck_t;
206
207 /*
208  * Define the extended attribute refcount structure
209  */
210 typedef struct ea_refcount *ext2_refcount_t;
211
212 struct e2fsck_struct {
213         ext2_filsys fs;
214         const char *program_name;
215         char *filesystem_name;
216         char *device_name;
217         char *io_options;
218         int     flags;          /* E2fsck internal flags */
219         int     options;
220         blk_t   use_superblock; /* sb requested by user */
221         blk_t   superblock;     /* sb used to open fs */
222         int     blocksize;      /* blocksize */
223         blk_t   num_blocks;     /* Total number of blocks */
224         int     mount_flags;
225         blkid_cache blkid;      /* blkid cache */
226
227         jmp_buf abort_loc;
228
229         unsigned long abort_code;
230
231         int (*progress)(e2fsck_t ctx, int pass, unsigned long cur,
232                         unsigned long max);
233
234         ext2fs_inode_bitmap inode_used_map; /* Inodes which are in use */
235         ext2fs_inode_bitmap inode_bad_map; /* Inodes which are bad somehow */
236         ext2fs_inode_bitmap inode_dir_map; /* Inodes which are directories */
237         ext2fs_inode_bitmap inode_bb_map; /* Inodes which are in bad blocks */
238         ext2fs_inode_bitmap inode_imagic_map; /* AFS inodes */
239         ext2fs_inode_bitmap inode_reg_map; /* Inodes which are regular files*/
240
241         ext2fs_block_bitmap block_found_map; /* Blocks which are in use */
242         ext2fs_block_bitmap block_dup_map; /* Blks referenced more than once */
243         ext2fs_block_bitmap block_ea_map; /* Blocks which are used by EA's */
244
245         /*
246          * Inode count arrays
247          */
248         ext2_icount_t   inode_count;
249         ext2_icount_t inode_link_info;
250
251         ext2_refcount_t refcount;
252         ext2_refcount_t refcount_extra;
253
254         /*
255          * Array of flags indicating whether an inode bitmap, block
256          * bitmap, or inode table is invalid
257          */
258         int *invalid_inode_bitmap_flag;
259         int *invalid_block_bitmap_flag;
260         int *invalid_inode_table_flag;
261         int invalid_bitmaps;    /* There are invalid bitmaps/itable */
262
263         /*
264          * Block buffer
265          */
266         char *block_buf;
267
268         /*
269          * For pass1_check_directory and pass1_get_blocks
270          */
271         ext2_ino_t stashed_ino;
272         struct ext2_inode *stashed_inode;
273
274         /*
275          * Location of the lost and found directory
276          */
277         ext2_ino_t lost_and_found;
278         int bad_lost_and_found;
279
280         /*
281          * Directory information
282          */
283         int             dir_info_count;
284         int             dir_info_size;
285         struct dir_info *dir_info;
286
287         /*
288          * Indexed directory information
289          */
290         int             dx_dir_info_count;
291         int             dx_dir_info_size;
292         struct dx_dir_info *dx_dir_info;
293
294         /*
295          * Directories to hash
296          */
297         ext2_u32_list   dirs_to_hash;
298
299         /*
300          * Tuning parameters
301          */
302         int process_inode_size;
303         int inode_buffer_blocks;
304
305         /*
306          * ext3 journal support
307          */
308         io_channel      journal_io;
309         char    *journal_name;
310
311 #ifdef RESOURCE_TRACK
312         /*
313          * For timing purposes
314          */
315         struct resource_track   global_rtrack;
316 #endif
317
318         /*
319          * How we display the progress update (for unix)
320          */
321         int progress_fd;
322         int progress_pos;
323         int progress_last_percent;
324         unsigned int progress_last_time;
325         int interactive;        /* Are we connected directly to a tty? */
326         char start_meta[2], stop_meta[2];
327
328         /* File counts */
329         int fs_directory_count;
330         int fs_regular_count;
331         int fs_blockdev_count;
332         int fs_chardev_count;
333         int fs_links_count;
334         int fs_symlinks_count;
335         int fs_fast_symlinks_count;
336         int fs_fifo_count;
337         int fs_total_count;
338         int fs_badblocks_count;
339         int fs_sockets_count;
340         int fs_ind_count;
341         int fs_dind_count;
342         int fs_tind_count;
343         int fs_fragmented;
344         int large_files;
345         int fs_ext_attr_inodes;
346         int fs_ext_attr_blocks;
347
348         int ext_attr_ver;
349
350         /*
351          * For the use of callers of the e2fsck functions; not used by
352          * e2fsck functions themselves.
353          */
354         void *priv_data;
355 };
356
357 /* Used by the region allocation code */
358 typedef __u32 region_addr_t;
359 typedef struct region_struct *region_t;
360
361 /*
362  * Procedure declarations
363  */
364
365 static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
366
367 /* pass1.c */
368 static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
369
370 /* pass2.c */
371 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
372                                     ext2_ino_t ino, char *buf);
373
374 /* pass3.c */
375 static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
376 static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
377                                          int num, int gauranteed_size);
378 static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
379 static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
380                                            int adj);
381
382 /* rehash.c */
383 static void e2fsck_rehash_directories(e2fsck_t ctx);
384
385 /* util.c */
386 static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
387                                     const char *description);
388 static int ask(e2fsck_t ctx, const char * string, int def);
389 static void e2fsck_read_bitmaps(e2fsck_t ctx);
390 static void preenhalt(e2fsck_t ctx);
391 #ifdef RESOURCE_TRACK
392 static void print_resource_track(const char *desc,
393                                  struct resource_track *track);
394 static void init_resource_track(struct resource_track *track);
395 #endif
396 static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
397                               struct ext2_inode * inode, const char * proc);
398 static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
399                                struct ext2_inode * inode, const char * proc);
400 #ifdef MTRACE
401 static void mtrace_print(char *mesg);
402 #endif
403 static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
404                            const char *name, io_manager manager);
405
406 /* unix.c */
407 static void e2fsck_clear_progbar(e2fsck_t ctx);
408 static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
409                                   float percent, unsigned int dpynum);
410 /*
411  * problem.h --- e2fsck problem error codes
412  */
413
414 typedef __u32 problem_t;
415
416 struct problem_context {
417         errcode_t       errcode;
418         ext2_ino_t ino, ino2, dir;
419         struct ext2_inode *inode;
420         struct ext2_dir_entry *dirent;
421         blk_t   blk, blk2;
422         e2_blkcnt_t     blkcount;
423         int             group;
424         __u64   num;
425         const char *str;
426 };
427
428 /*
429  * We define a set of "latch groups"; these are problems which are
430  * handled as a set.  The user answers once for a particular latch
431  * group.
432  */
433 #define PR_LATCH_MASK         0x0ff0 /* Latch mask */
434 #define PR_LATCH_BLOCK        0x0010 /* Latch for illegal blocks (pass 1) */
435 #define PR_LATCH_BBLOCK       0x0020 /* Latch for bad block inode blocks (pass 1) */
436 #define PR_LATCH_IBITMAP      0x0030 /* Latch for pass 5 inode bitmap proc. */
437 #define PR_LATCH_BBITMAP      0x0040 /* Latch for pass 5 inode bitmap proc. */
438 #define PR_LATCH_RELOC        0x0050 /* Latch for superblock relocate hint */
439 #define PR_LATCH_DBLOCK       0x0060 /* Latch for pass 1b dup block headers */
440 #define PR_LATCH_LOW_DTIME    0x0070 /* Latch for pass1 orphaned list refugees */
441 #define PR_LATCH_TOOBIG       0x0080 /* Latch for file to big errors */
442 #define PR_LATCH_OPTIMIZE_DIR 0x0090 /* Latch for optimize directories */
443
444 #define PR_LATCH(x)     ((((x) & PR_LATCH_MASK) >> 4) - 1)
445
446 /*
447  * Latch group descriptor flags
448  */
449 #define PRL_YES         0x0001  /* Answer yes */
450 #define PRL_NO          0x0002  /* Answer no */
451 #define PRL_LATCHED     0x0004  /* The latch group is latched */
452 #define PRL_SUPPRESS    0x0008  /* Suppress all latch group questions */
453
454 #define PRL_VARIABLE    0x000f  /* All the flags that need to be reset */
455
456 /*
457  * Pre-Pass 1 errors
458  */
459
460 /* Block bitmap not in group */
461 #define PR_0_BB_NOT_GROUP       0x000001
462
463 /* Inode bitmap not in group */
464 #define PR_0_IB_NOT_GROUP       0x000002
465
466 /* Inode table not in group */
467 #define PR_0_ITABLE_NOT_GROUP   0x000003
468
469 /* Superblock corrupt */
470 #define PR_0_SB_CORRUPT         0x000004
471
472 /* Filesystem size is wrong */
473 #define PR_0_FS_SIZE_WRONG      0x000005
474
475 /* Fragments not supported */
476 #define PR_0_NO_FRAGMENTS       0x000006
477
478 /* Bad blocks_per_group */
479 #define PR_0_BLOCKS_PER_GROUP   0x000007
480
481 /* Bad first_data_block */
482 #define PR_0_FIRST_DATA_BLOCK   0x000008
483
484 /* Adding UUID to filesystem */
485 #define PR_0_ADD_UUID           0x000009
486
487 /* Relocate hint */
488 #define PR_0_RELOCATE_HINT      0x00000A
489
490 /* Miscellaneous superblock corruption */
491 #define PR_0_MISC_CORRUPT_SUPER 0x00000B
492
493 /* Error determing physical device size of filesystem */
494 #define PR_0_GETSIZE_ERROR      0x00000C
495
496 /* Inode count in the superblock incorrect */
497 #define PR_0_INODE_COUNT_WRONG  0x00000D
498
499 /* The Hurd does not support the filetype feature */
500 #define PR_0_HURD_CLEAR_FILETYPE 0x00000E
501
502 /* Journal inode is invalid */
503 #define PR_0_JOURNAL_BAD_INODE  0x00000F
504
505 /* The external journal has multiple filesystems (which we can't handle yet) */
506 #define PR_0_JOURNAL_UNSUPP_MULTIFS 0x000010
507
508 /* Can't find external journal */
509 #define PR_0_CANT_FIND_JOURNAL  0x000011
510
511 /* External journal has bad superblock */
512 #define PR_0_EXT_JOURNAL_BAD_SUPER 0x000012
513
514 /* Superblock has a bad journal UUID */
515 #define PR_0_JOURNAL_BAD_UUID   0x000013
516
517 /* Journal has an unknown superblock type */
518 #define PR_0_JOURNAL_UNSUPP_SUPER 0x000014
519
520 /* Journal superblock is corrupt */
521 #define PR_0_JOURNAL_BAD_SUPER  0x000015
522
523 /* Journal superblock is corrupt */
524 #define PR_0_JOURNAL_HAS_JOURNAL 0x000016
525
526 /* Superblock has recovery flag set but no journal */
527 #define PR_0_JOURNAL_RECOVER_SET 0x000017
528
529 /* Journal has data, but recovery flag is clear */
530 #define PR_0_JOURNAL_RECOVERY_CLEAR 0x000018
531
532 /* Ask if we should clear the journal */
533 #define PR_0_JOURNAL_RESET_JOURNAL 0x000019
534
535 /* Filesystem revision is 0, but feature flags are set */
536 #define PR_0_FS_REV_LEVEL       0x00001A
537
538 /* Clearing orphan inode */
539 #define PR_0_ORPHAN_CLEAR_INODE                 0x000020
540
541 /* Illegal block found in orphaned inode */
542 #define PR_0_ORPHAN_ILLEGAL_BLOCK_NUM           0x000021
543
544 /* Already cleared block found in orphaned inode */
545 #define PR_0_ORPHAN_ALREADY_CLEARED_BLOCK       0x000022
546
547 /* Illegal orphan inode in superblock */
548 #define PR_0_ORPHAN_ILLEGAL_HEAD_INODE          0x000023
549
550 /* Illegal inode in orphaned inode list */
551 #define PR_0_ORPHAN_ILLEGAL_INODE               0x000024
552
553 /* Journal has unsupported read-only feature - abort */
554 #define PR_0_JOURNAL_UNSUPP_ROCOMPAT            0x000025
555
556 /* Journal has unsupported incompatible feature - abort */
557 #define PR_0_JOURNAL_UNSUPP_INCOMPAT            0x000026
558
559 /* Journal has unsupported version number */
560 #define PR_0_JOURNAL_UNSUPP_VERSION             0x000027
561
562 /* Moving journal to hidden file */
563 #define PR_0_MOVE_JOURNAL                       0x000028
564
565 /* Error moving journal */
566 #define PR_0_ERR_MOVE_JOURNAL                   0x000029
567
568 /* Clearing V2 journal superblock */
569 #define PR_0_CLEAR_V2_JOURNAL                   0x00002A
570
571 /* Run journal anyway */
572 #define PR_0_JOURNAL_RUN                        0x00002B
573
574 /* Run journal anyway by default */
575 #define PR_0_JOURNAL_RUN_DEFAULT                0x00002C
576
577 /* Backup journal inode blocks */
578 #define PR_0_BACKUP_JNL                         0x00002D
579
580 /* Reserved blocks w/o resize_inode */
581 #define PR_0_NONZERO_RESERVED_GDT_BLOCKS        0x00002E
582
583 /* Resize_inode not enabled, but resize inode is non-zero */
584 #define PR_0_CLEAR_RESIZE_INODE                 0x00002F
585
586 /* Resize inode invalid */
587 #define PR_0_RESIZE_INODE_INVALID               0x000030
588
589 /*
590  * Pass 1 errors
591  */
592
593 /* Pass 1: Checking inodes, blocks, and sizes */
594 #define PR_1_PASS_HEADER                0x010000
595
596 /* Root directory is not an inode */
597 #define PR_1_ROOT_NO_DIR                0x010001
598
599 /* Root directory has dtime set */
600 #define PR_1_ROOT_DTIME                 0x010002
601
602 /* Reserved inode has bad mode */
603 #define PR_1_RESERVED_BAD_MODE          0x010003
604
605 /* Deleted inode has zero dtime */
606 #define PR_1_ZERO_DTIME                 0x010004
607
608 /* Inode in use, but dtime set */
609 #define PR_1_SET_DTIME                  0x010005
610
611 /* Zero-length directory */
612 #define PR_1_ZERO_LENGTH_DIR            0x010006
613
614 /* Block bitmap conflicts with some other fs block */
615 #define PR_1_BB_CONFLICT                0x010007
616
617 /* Inode bitmap conflicts with some other fs block */
618 #define PR_1_IB_CONFLICT                0x010008
619
620 /* Inode table conflicts with some other fs block */
621 #define PR_1_ITABLE_CONFLICT            0x010009
622
623 /* Block bitmap is on a bad block */
624 #define PR_1_BB_BAD_BLOCK               0x01000A
625
626 /* Inode bitmap is on a bad block */
627 #define PR_1_IB_BAD_BLOCK               0x01000B
628
629 /* Inode has incorrect i_size */
630 #define PR_1_BAD_I_SIZE                 0x01000C
631
632 /* Inode has incorrect i_blocks */
633 #define PR_1_BAD_I_BLOCKS               0x01000D
634
635 /* Illegal block number in inode */
636 #define PR_1_ILLEGAL_BLOCK_NUM          0x01000E
637
638 /* Block number overlaps fs metadata */
639 #define PR_1_BLOCK_OVERLAPS_METADATA    0x01000F
640
641 /* Inode has illegal blocks (latch question) */
642 #define PR_1_INODE_BLOCK_LATCH          0x010010
643
644 /* Too many bad blocks in inode */
645 #define PR_1_TOO_MANY_BAD_BLOCKS        0x010011
646
647 /* Illegal block number in bad block inode */
648 #define PR_1_BB_ILLEGAL_BLOCK_NUM       0x010012
649
650 /* Bad block inode has illegal blocks (latch question) */
651 #define PR_1_INODE_BBLOCK_LATCH         0x010013
652
653 /* Duplicate or bad blocks in use! */
654 #define PR_1_DUP_BLOCKS_PREENSTOP       0x010014
655
656 /* Bad block used as bad block indirect block */
657 #define PR_1_BBINODE_BAD_METABLOCK      0x010015
658
659 /* Inconsistency can't be fixed prompt */
660 #define PR_1_BBINODE_BAD_METABLOCK_PROMPT 0x010016
661
662 /* Bad primary block */
663 #define PR_1_BAD_PRIMARY_BLOCK          0x010017
664
665 /* Bad primary block prompt */
666 #define PR_1_BAD_PRIMARY_BLOCK_PROMPT   0x010018
667
668 /* Bad primary superblock */
669 #define PR_1_BAD_PRIMARY_SUPERBLOCK     0x010019
670
671 /* Bad primary block group descriptors */
672 #define PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR 0x01001A
673
674 /* Bad superblock in group */
675 #define PR_1_BAD_SUPERBLOCK             0x01001B
676
677 /* Bad block group descriptors in group */
678 #define PR_1_BAD_GROUP_DESCRIPTORS      0x01001C
679
680 /* Block claimed for no reason */
681 #define PR_1_PROGERR_CLAIMED_BLOCK      0x01001D
682
683 /* Error allocating blocks for relocating metadata */
684 #define PR_1_RELOC_BLOCK_ALLOCATE       0x01001E
685
686 /* Error allocating block buffer during relocation process */
687 #define PR_1_RELOC_MEMORY_ALLOCATE      0x01001F
688
689 /* Relocating metadata group information from X to Y */
690 #define PR_1_RELOC_FROM_TO              0x010020
691
692 /* Relocating metatdata group information to X */
693 #define PR_1_RELOC_TO                   0x010021
694
695 /* Block read error during relocation process */
696 #define PR_1_RELOC_READ_ERR             0x010022
697
698 /* Block write error during relocation process */
699 #define PR_1_RELOC_WRITE_ERR            0x010023
700
701 /* Error allocating inode bitmap */
702 #define PR_1_ALLOCATE_IBITMAP_ERROR     0x010024
703
704 /* Error allocating block bitmap */
705 #define PR_1_ALLOCATE_BBITMAP_ERROR     0x010025
706
707 /* Error allocating icount structure */
708 #define PR_1_ALLOCATE_ICOUNT            0x010026
709
710 /* Error allocating dbcount */
711 #define PR_1_ALLOCATE_DBCOUNT           0x010027
712
713 /* Error while scanning inodes */
714 #define PR_1_ISCAN_ERROR                0x010028
715
716 /* Error while iterating over blocks */
717 #define PR_1_BLOCK_ITERATE              0x010029
718
719 /* Error while storing inode count information */
720 #define PR_1_ICOUNT_STORE               0x01002A
721
722 /* Error while storing directory block information */
723 #define PR_1_ADD_DBLOCK                 0x01002B
724
725 /* Error while reading inode (for clearing) */
726 #define PR_1_READ_INODE                 0x01002C
727
728 /* Suppress messages prompt */
729 #define PR_1_SUPPRESS_MESSAGES          0x01002D
730
731 /* Imagic flag set on an inode when filesystem doesn't support it */
732 #define PR_1_SET_IMAGIC                 0x01002F
733
734 /* Immutable flag set on a device or socket inode */
735 #define PR_1_SET_IMMUTABLE              0x010030
736
737 /* Compression flag set on a non-compressed filesystem */
738 #define PR_1_COMPR_SET                  0x010031
739
740 /* Non-zero size on on device, fifo or socket inode */
741 #define PR_1_SET_NONZSIZE               0x010032
742
743 /* Filesystem revision is 0, but feature flags are set */
744 #define PR_1_FS_REV_LEVEL               0x010033
745
746 /* Journal inode not in use, needs clearing */
747 #define PR_1_JOURNAL_INODE_NOT_CLEAR    0x010034
748
749 /* Journal inode has wrong mode */
750 #define PR_1_JOURNAL_BAD_MODE           0x010035
751
752 /* Inode that was part of orphan linked list */
753 #define PR_1_LOW_DTIME                  0x010036
754
755 /* Latch question which asks how to deal with low dtime inodes */
756 #define PR_1_ORPHAN_LIST_REFUGEES       0x010037
757
758 /* Error allocating refcount structure */
759 #define PR_1_ALLOCATE_REFCOUNT          0x010038
760
761 /* Error reading Extended Attribute block */
762 #define PR_1_READ_EA_BLOCK              0x010039
763
764 /* Invalid Extended Attribute block */
765 #define PR_1_BAD_EA_BLOCK               0x01003A
766
767 /* Error reading Extended Attribute block while fixing refcount -- abort */
768 #define PR_1_EXTATTR_READ_ABORT         0x01003B
769
770 /* Extended attribute reference count incorrect */
771 #define PR_1_EXTATTR_REFCOUNT           0x01003C
772
773 /* Error writing Extended Attribute block while fixing refcount */
774 #define PR_1_EXTATTR_WRITE              0x01003D
775
776 /* Multiple EA blocks not supported */
777 #define PR_1_EA_MULTI_BLOCK             0x01003E
778
779 /* Error allocating EA region allocation structure */
780 #define PR_1_EA_ALLOC_REGION            0x01003F
781
782 /* Error EA allocation collision */
783 #define PR_1_EA_ALLOC_COLLISION         0x010040
784
785 /* Bad extended attribute name */
786 #define PR_1_EA_BAD_NAME                0x010041
787
788 /* Bad extended attribute value */
789 #define PR_1_EA_BAD_VALUE               0x010042
790
791 /* Inode too big (latch question) */
792 #define PR_1_INODE_TOOBIG               0x010043
793
794 /* Directory too big */
795 #define PR_1_TOOBIG_DIR                 0x010044
796
797 /* Regular file too big */
798 #define PR_1_TOOBIG_REG                 0x010045
799
800 /* Symlink too big */
801 #define PR_1_TOOBIG_SYMLINK             0x010046
802
803 /* INDEX_FL flag set on a non-HTREE filesystem */
804 #define PR_1_HTREE_SET                  0x010047
805
806 /* INDEX_FL flag set on a non-directory */
807 #define PR_1_HTREE_NODIR                0x010048
808
809 /* Invalid root node in HTREE directory */
810 #define PR_1_HTREE_BADROOT              0x010049
811
812 /* Unsupported hash version in HTREE directory */
813 #define PR_1_HTREE_HASHV                0x01004A
814
815 /* Incompatible flag in HTREE root node */
816 #define PR_1_HTREE_INCOMPAT             0x01004B
817
818 /* HTREE too deep */
819 #define PR_1_HTREE_DEPTH                0x01004C
820
821 /* Bad block has indirect block that conflicts with filesystem block */
822 #define PR_1_BB_FS_BLOCK                0x01004D
823
824 /* Resize inode failed */
825 #define PR_1_RESIZE_INODE_CREATE        0x01004E
826
827 /* inode->i_size is too long */
828 #define PR_1_EXTRA_ISIZE                0x01004F
829
830 /* attribute name is too long */
831 #define PR_1_ATTR_NAME_LEN              0x010050
832
833 /* wrong EA value offset */
834 #define PR_1_ATTR_VALUE_OFFSET          0x010051
835
836 /* wrong EA blocknumber */
837 #define PR_1_ATTR_VALUE_BLOCK           0x010052
838
839 /* wrong EA value size */
840 #define PR_1_ATTR_VALUE_SIZE            0x010053
841
842 /* wrong EA hash value */
843 #define PR_1_ATTR_HASH                  0x010054
844
845 /*
846  * Pass 1b errors
847  */
848
849 /* Pass 1B: Rescan for duplicate/bad blocks */
850 #define PR_1B_PASS_HEADER       0x011000
851
852 /* Duplicate/bad block(s) header */
853 #define PR_1B_DUP_BLOCK_HEADER  0x011001
854
855 /* Duplicate/bad block(s) in inode */
856 #define PR_1B_DUP_BLOCK         0x011002
857
858 /* Duplicate/bad block(s) end */
859 #define PR_1B_DUP_BLOCK_END     0x011003
860
861 /* Error while scanning inodes */
862 #define PR_1B_ISCAN_ERROR       0x011004
863
864 /* Error allocating inode bitmap */
865 #define PR_1B_ALLOCATE_IBITMAP_ERROR 0x011005
866
867 /* Error while iterating over blocks */
868 #define PR_1B_BLOCK_ITERATE     0x0110006
869
870 /* Error adjusting EA refcount */
871 #define PR_1B_ADJ_EA_REFCOUNT   0x0110007
872
873
874 /* Pass 1C: Scan directories for inodes with dup blocks. */
875 #define PR_1C_PASS_HEADER       0x012000
876
877
878 /* Pass 1D: Reconciling duplicate blocks */
879 #define PR_1D_PASS_HEADER       0x013000
880
881 /* File has duplicate blocks */
882 #define PR_1D_DUP_FILE          0x013001
883
884 /* List of files sharing duplicate blocks */
885 #define PR_1D_DUP_FILE_LIST     0x013002
886
887 /* File sharing blocks with filesystem metadata  */
888 #define PR_1D_SHARE_METADATA    0x013003
889
890 /* Report of how many duplicate/bad inodes */
891 #define PR_1D_NUM_DUP_INODES    0x013004
892
893 /* Duplicated blocks already reassigned or cloned. */
894 #define PR_1D_DUP_BLOCKS_DEALT  0x013005
895
896 /* Clone duplicate/bad blocks? */
897 #define PR_1D_CLONE_QUESTION    0x013006
898
899 /* Delete file? */
900 #define PR_1D_DELETE_QUESTION   0x013007
901
902 /* Couldn't clone file (error) */
903 #define PR_1D_CLONE_ERROR       0x013008
904
905 /*
906  * Pass 2 errors
907  */
908
909 /* Pass 2: Checking directory structure */
910 #define PR_2_PASS_HEADER        0x020000
911
912 /* Bad inode number for '.' */
913 #define PR_2_BAD_INODE_DOT      0x020001
914
915 /* Directory entry has bad inode number */
916 #define PR_2_BAD_INO            0x020002
917
918 /* Directory entry has deleted or unused inode */
919 #define PR_2_UNUSED_INODE       0x020003
920
921 /* Directry entry is link to '.' */
922 #define PR_2_LINK_DOT           0x020004
923
924 /* Directory entry points to inode now located in a bad block */
925 #define PR_2_BB_INODE           0x020005
926
927 /* Directory entry contains a link to a directory */
928 #define PR_2_LINK_DIR           0x020006
929
930 /* Directory entry contains a link to the root directry */
931 #define PR_2_LINK_ROOT          0x020007
932
933 /* Directory entry has illegal characters in its name */
934 #define PR_2_BAD_NAME           0x020008
935
936 /* Missing '.' in directory inode */
937 #define PR_2_MISSING_DOT        0x020009
938
939 /* Missing '..' in directory inode */
940 #define PR_2_MISSING_DOT_DOT    0x02000A
941
942 /* First entry in directory inode doesn't contain '.' */
943 #define PR_2_1ST_NOT_DOT        0x02000B
944
945 /* Second entry in directory inode doesn't contain '..' */
946 #define PR_2_2ND_NOT_DOT_DOT    0x02000C
947
948 /* i_faddr should be zero */
949 #define PR_2_FADDR_ZERO         0x02000D
950
951 /* i_file_acl should be zero */
952 #define PR_2_FILE_ACL_ZERO      0x02000E
953
954 /* i_dir_acl should be zero */
955 #define PR_2_DIR_ACL_ZERO       0x02000F
956
957 /* i_frag should be zero */
958 #define PR_2_FRAG_ZERO          0x020010
959
960 /* i_fsize should be zero */
961 #define PR_2_FSIZE_ZERO         0x020011
962
963 /* inode has bad mode */
964 #define PR_2_BAD_MODE           0x020012
965
966 /* directory corrupted */
967 #define PR_2_DIR_CORRUPTED      0x020013
968
969 /* filename too long */
970 #define PR_2_FILENAME_LONG      0x020014
971
972 /* Directory inode has a missing block (hole) */
973 #define PR_2_DIRECTORY_HOLE     0x020015
974
975 /* '.' is not NULL terminated */
976 #define PR_2_DOT_NULL_TERM      0x020016
977
978 /* '..' is not NULL terminated */
979 #define PR_2_DOT_DOT_NULL_TERM  0x020017
980
981 /* Illegal character device in inode */
982 #define PR_2_BAD_CHAR_DEV       0x020018
983
984 /* Illegal block device in inode */
985 #define PR_2_BAD_BLOCK_DEV      0x020019
986
987 /* Duplicate '.' entry */
988 #define PR_2_DUP_DOT            0x02001A
989
990 /* Duplicate '..' entry */
991 #define PR_2_DUP_DOT_DOT        0x02001B
992
993 /* Internal error: couldn't find dir_info */
994 #define PR_2_NO_DIRINFO         0x02001C
995
996 /* Final rec_len is wrong */
997 #define PR_2_FINAL_RECLEN       0x02001D
998
999 /* Error allocating icount structure */
1000 #define PR_2_ALLOCATE_ICOUNT    0x02001E
1001
1002 /* Error iterating over directory blocks */
1003 #define PR_2_DBLIST_ITERATE     0x02001F
1004
1005 /* Error reading directory block */
1006 #define PR_2_READ_DIRBLOCK      0x020020
1007
1008 /* Error writing directory block */
1009 #define PR_2_WRITE_DIRBLOCK     0x020021
1010
1011 /* Error allocating new directory block */
1012 #define PR_2_ALLOC_DIRBOCK      0x020022
1013
1014 /* Error deallocating inode */
1015 #define PR_2_DEALLOC_INODE      0x020023
1016
1017 /* Directory entry for '.' is big.  Split? */
1018 #define PR_2_SPLIT_DOT          0x020024
1019
1020 /* Illegal FIFO */
1021 #define PR_2_BAD_FIFO           0x020025
1022
1023 /* Illegal socket */
1024 #define PR_2_BAD_SOCKET         0x020026
1025
1026 /* Directory filetype not set */
1027 #define PR_2_SET_FILETYPE       0x020027
1028
1029 /* Directory filetype incorrect */
1030 #define PR_2_BAD_FILETYPE       0x020028
1031
1032 /* Directory filetype set when it shouldn't be */
1033 #define PR_2_CLEAR_FILETYPE     0x020029
1034
1035 /* Directory filename can't be zero-length  */
1036 #define PR_2_NULL_NAME          0x020030
1037
1038 /* Invalid symlink */
1039 #define PR_2_INVALID_SYMLINK    0x020031
1040
1041 /* i_file_acl (extended attribute) is bad */
1042 #define PR_2_FILE_ACL_BAD       0x020032
1043
1044 /* Filesystem contains large files, but has no such flag in sb */
1045 #define PR_2_FEATURE_LARGE_FILES 0x020033
1046
1047 /* Node in HTREE directory not referenced */
1048 #define PR_2_HTREE_NOTREF       0x020034
1049
1050 /* Node in HTREE directory referenced twice */
1051 #define PR_2_HTREE_DUPREF       0x020035
1052
1053 /* Node in HTREE directory has bad min hash */
1054 #define PR_2_HTREE_MIN_HASH     0x020036
1055
1056 /* Node in HTREE directory has bad max hash */
1057 #define PR_2_HTREE_MAX_HASH     0x020037
1058
1059 /* Clear invalid HTREE directory */
1060 #define PR_2_HTREE_CLEAR        0x020038
1061
1062 /* Clear the htree flag forcibly */
1063 /* #define PR_2_HTREE_FCLR      0x020039 */
1064
1065 /* Bad block in htree interior node */
1066 #define PR_2_HTREE_BADBLK       0x02003A
1067
1068 /* Error adjusting EA refcount */
1069 #define PR_2_ADJ_EA_REFCOUNT    0x02003B
1070
1071 /* Invalid HTREE root node */
1072 #define PR_2_HTREE_BAD_ROOT     0x02003C
1073
1074 /* Invalid HTREE limit */
1075 #define PR_2_HTREE_BAD_LIMIT    0x02003D
1076
1077 /* Invalid HTREE count */
1078 #define PR_2_HTREE_BAD_COUNT    0x02003E
1079
1080 /* HTREE interior node has out-of-order hashes in table */
1081 #define PR_2_HTREE_HASH_ORDER   0x02003F
1082
1083 /* Node in HTREE directory has bad depth */
1084 #define PR_2_HTREE_BAD_DEPTH    0x020040
1085
1086 /* Duplicate directory entry found */
1087 #define PR_2_DUPLICATE_DIRENT   0x020041
1088
1089 /* Non-unique filename found */
1090 #define PR_2_NON_UNIQUE_FILE    0x020042
1091
1092 /* Duplicate directory entry found */
1093 #define PR_2_REPORT_DUP_DIRENT  0x020043
1094
1095 /*
1096  * Pass 3 errors
1097  */
1098
1099 /* Pass 3: Checking directory connectivity */
1100 #define PR_3_PASS_HEADER                0x030000
1101
1102 /* Root inode not allocated */
1103 #define PR_3_NO_ROOT_INODE              0x030001
1104
1105 /* No room in lost+found */
1106 #define PR_3_EXPAND_LF_DIR              0x030002
1107
1108 /* Unconnected directory inode */
1109 #define PR_3_UNCONNECTED_DIR            0x030003
1110
1111 /* /lost+found not found */
1112 #define PR_3_NO_LF_DIR                  0x030004
1113
1114 /* .. entry is incorrect */
1115 #define PR_3_BAD_DOT_DOT                0x030005
1116
1117 /* Bad or non-existent /lost+found.  Cannot reconnect */
1118 #define PR_3_NO_LPF                     0x030006
1119
1120 /* Could not expand /lost+found */
1121 #define PR_3_CANT_EXPAND_LPF            0x030007
1122
1123 /* Could not reconnect inode */
1124 #define PR_3_CANT_RECONNECT             0x030008
1125
1126 /* Error while trying to find /lost+found */
1127 #define PR_3_ERR_FIND_LPF               0x030009
1128
1129 /* Error in ext2fs_new_block while creating /lost+found */
1130 #define PR_3_ERR_LPF_NEW_BLOCK          0x03000A
1131
1132 /* Error in ext2fs_new_inode while creating /lost+found */
1133 #define PR_3_ERR_LPF_NEW_INODE          0x03000B
1134
1135 /* Error in ext2fs_new_dir_block while creating /lost+found */
1136 #define PR_3_ERR_LPF_NEW_DIR_BLOCK      0x03000C
1137
1138 /* Error while writing directory block for /lost+found */
1139 #define PR_3_ERR_LPF_WRITE_BLOCK        0x03000D
1140
1141 /* Error while adjusting inode count */
1142 #define PR_3_ADJUST_INODE               0x03000E
1143
1144 /* Couldn't fix parent directory -- error */
1145 #define PR_3_FIX_PARENT_ERR             0x03000F
1146
1147 /* Couldn't fix parent directory -- couldn't find it */
1148 #define PR_3_FIX_PARENT_NOFIND          0x030010
1149
1150 /* Error allocating inode bitmap */
1151 #define PR_3_ALLOCATE_IBITMAP_ERROR     0x030011
1152
1153 /* Error creating root directory */
1154 #define PR_3_CREATE_ROOT_ERROR          0x030012
1155
1156 /* Error creating lost and found directory */
1157 #define PR_3_CREATE_LPF_ERROR           0x030013
1158
1159 /* Root inode is not directory; aborting */
1160 #define PR_3_ROOT_NOT_DIR_ABORT         0x030014
1161
1162 /* Cannot proceed without a root inode. */
1163 #define PR_3_NO_ROOT_INODE_ABORT        0x030015
1164
1165 /* Internal error: couldn't find dir_info */
1166 #define PR_3_NO_DIRINFO                 0x030016
1167
1168 /* Lost+found is not a directory */
1169 #define PR_3_LPF_NOTDIR                 0x030017
1170
1171 /*
1172  * Pass 3a --- rehashing diretories
1173  */
1174 /* Pass 3a: Reindexing directories */
1175 #define PR_3A_PASS_HEADER               0x031000
1176
1177 /* Error iterating over directories */
1178 #define PR_3A_OPTIMIZE_ITER             0x031001
1179
1180 /* Error rehash directory */
1181 #define PR_3A_OPTIMIZE_DIR_ERR          0x031002
1182
1183 /* Rehashing dir header */
1184 #define PR_3A_OPTIMIZE_DIR_HEADER               0x031003
1185
1186 /* Rehashing directory %d */
1187 #define PR_3A_OPTIMIZE_DIR              0x031004
1188
1189 /* Rehashing dir end */
1190 #define PR_3A_OPTIMIZE_DIR_END          0x031005
1191
1192 /*
1193  * Pass 4 errors
1194  */
1195
1196 /* Pass 4: Checking reference counts */
1197 #define PR_4_PASS_HEADER        0x040000
1198
1199 /* Unattached zero-length inode */
1200 #define PR_4_ZERO_LEN_INODE     0x040001
1201
1202 /* Unattached inode */
1203 #define PR_4_UNATTACHED_INODE   0x040002
1204
1205 /* Inode ref count wrong */
1206 #define PR_4_BAD_REF_COUNT      0x040003
1207
1208 /* Inconsistent inode count information cached */
1209 #define PR_4_INCONSISTENT_COUNT 0x040004
1210
1211 /*
1212  * Pass 5 errors
1213  */
1214
1215 /* Pass 5: Checking group summary information */
1216 #define PR_5_PASS_HEADER                0x050000
1217
1218 /* Padding at end of inode bitmap is not set. */
1219 #define PR_5_INODE_BMAP_PADDING         0x050001
1220
1221 /* Padding at end of block bitmap is not set. */
1222 #define PR_5_BLOCK_BMAP_PADDING         0x050002
1223
1224 /* Block bitmap differences header */
1225 #define PR_5_BLOCK_BITMAP_HEADER        0x050003
1226
1227 /* Block not used, but marked in bitmap */
1228 #define PR_5_BLOCK_UNUSED               0x050004
1229
1230 /* Block used, but not marked used in bitmap */
1231 #define PR_5_BLOCK_USED                 0x050005
1232
1233 /* Block bitmap differences end */
1234 #define PR_5_BLOCK_BITMAP_END           0x050006
1235
1236 /* Inode bitmap differences header */
1237 #define PR_5_INODE_BITMAP_HEADER        0x050007
1238
1239 /* Inode not used, but marked in bitmap */
1240 #define PR_5_INODE_UNUSED               0x050008
1241
1242 /* Inode used, but not marked used in bitmap */
1243 #define PR_5_INODE_USED                 0x050009
1244
1245 /* Inode bitmap differences end */
1246 #define PR_5_INODE_BITMAP_END           0x05000A
1247
1248 /* Free inodes count for group wrong */
1249 #define PR_5_FREE_INODE_COUNT_GROUP     0x05000B
1250
1251 /* Directories count for group wrong */
1252 #define PR_5_FREE_DIR_COUNT_GROUP       0x05000C
1253
1254 /* Free inodes count wrong */
1255 #define PR_5_FREE_INODE_COUNT   0x05000D
1256
1257 /* Free blocks count for group wrong */
1258 #define PR_5_FREE_BLOCK_COUNT_GROUP     0x05000E
1259
1260 /* Free blocks count wrong */
1261 #define PR_5_FREE_BLOCK_COUNT           0x05000F
1262
1263 /* Programming error: bitmap endpoints don't match */
1264 #define PR_5_BMAP_ENDPOINTS             0x050010
1265
1266 /* Internal error: fudging end of bitmap */
1267 #define PR_5_FUDGE_BITMAP_ERROR         0x050011
1268
1269 /* Error copying in replacement inode bitmap */
1270 #define PR_5_COPY_IBITMAP_ERROR         0x050012
1271
1272 /* Error copying in replacement block bitmap */
1273 #define PR_5_COPY_BBITMAP_ERROR         0x050013
1274
1275 /* Block range not used, but marked in bitmap */
1276 #define PR_5_BLOCK_RANGE_UNUSED         0x050014
1277
1278 /* Block range used, but not marked used in bitmap */
1279 #define PR_5_BLOCK_RANGE_USED           0x050015
1280
1281 /* Inode range not used, but marked in bitmap */
1282 #define PR_5_INODE_RANGE_UNUSED         0x050016
1283
1284 /* Inode rangeused, but not marked used in bitmap */
1285 #define PR_5_INODE_RANGE_USED           0x050017
1286
1287 /*
1288  * Function declarations
1289  */
1290 static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
1291 static int end_problem_latch(e2fsck_t ctx, int mask);
1292 static int set_latch_flags(int mask, int setflags, int clearflags);
1293 static void clear_problem_context(struct problem_context *ctx);
1294
1295 /*
1296  * Dictionary Abstract Data Type
1297  * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
1298  *
1299  * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
1300  * kazlib_1_20
1301  */
1302
1303 #ifndef DICT_H
1304 #define DICT_H
1305
1306 /*
1307  * Blurb for inclusion into C++ translation units
1308  */
1309
1310 typedef unsigned long dictcount_t;
1311 #define DICTCOUNT_T_MAX ULONG_MAX
1312
1313 /*
1314  * The dictionary is implemented as a red-black tree
1315  */
1316
1317 typedef enum { dnode_red, dnode_black } dnode_color_t;
1318
1319 typedef struct dnode_t {
1320     struct dnode_t *dict_left;
1321     struct dnode_t *dict_right;
1322     struct dnode_t *dict_parent;
1323     dnode_color_t dict_color;
1324     const void *dict_key;
1325     void *dict_data;
1326 } dnode_t;
1327
1328 typedef int (*dict_comp_t)(const void *, const void *);
1329 typedef void (*dnode_free_t)(dnode_t *);
1330
1331 typedef struct dict_t {
1332     dnode_t dict_nilnode;
1333     dictcount_t dict_nodecount;
1334     dictcount_t dict_maxcount;
1335     dict_comp_t dict_compare;
1336     dnode_free_t dict_freenode;
1337     int dict_dupes;
1338 } dict_t;
1339
1340 typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
1341
1342 typedef struct dict_load_t {
1343     dict_t *dict_dictptr;
1344     dnode_t dict_nilnode;
1345 } dict_load_t;
1346
1347 #define dict_count(D) ((D)->dict_nodecount)
1348 #define dnode_get(N) ((N)->dict_data)
1349 #define dnode_getkey(N) ((N)->dict_key)
1350
1351 #endif
1352
1353 /*
1354  * Compatibility header file for e2fsck which should be included
1355  * instead of linux/jfs.h
1356  *
1357  * Copyright (C) 2000 Stephen C. Tweedie
1358  */
1359
1360 /*
1361  * Pull in the definition of the e2fsck context structure
1362  */
1363
1364
1365 struct buffer_head {
1366         char            b_data[8192];
1367         e2fsck_t        b_ctx;
1368         io_channel      b_io;
1369         int             b_size;
1370         blk_t           b_blocknr;
1371         int             b_dirty;
1372         int             b_uptodate;
1373         int             b_err;
1374 };
1375
1376 struct inode {
1377         e2fsck_t        i_ctx;
1378         ext2_ino_t      i_ino;
1379         struct ext2_inode i_ext2;
1380 };
1381
1382 struct kdev_s {
1383         e2fsck_t        k_ctx;
1384         int             k_dev;
1385 };
1386
1387 #define K_DEV_FS        1
1388 #define K_DEV_JOURNAL   2
1389
1390 typedef struct kdev_s *kdev_t;
1391
1392 #define lock_buffer(bh) do {} while(0)
1393 #define unlock_buffer(bh) do {} while(0)
1394 #define buffer_req(bh) 1
1395 #define do_readahead(journal, start) do {} while(0)
1396
1397 static e2fsck_t e2fsck_global_ctx;  /* Try your very best not to use this! */
1398
1399 typedef struct {
1400         int     object_length;
1401 } kmem_cache_t;
1402
1403 #define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
1404
1405 /*
1406  * We use the standard libext2fs portability tricks for inline
1407  * functions.
1408  */
1409
1410 static _INLINE_ kmem_cache_t * do_cache_create(int len)
1411 {
1412         kmem_cache_t *new_cache;
1413
1414         new_cache = malloc(sizeof(*new_cache));
1415         if (new_cache)
1416                 new_cache->object_length = len;
1417         return new_cache;
1418 }
1419
1420 static _INLINE_ void do_cache_destroy(kmem_cache_t *cache)
1421 {
1422         free(cache);
1423 }
1424
1425 /*
1426  * Now pull in the real linux/jfs.h definitions.
1427  */
1428 #include "ext2fs/kernel-jbd.h"
1429
1430 /*
1431  * badblocks.c --- replace/append bad blocks to the bad block inode
1432  */
1433
1434 static int check_bb_inode_blocks(ext2_filsys fs, blk_t *block_nr, int blockcnt,
1435                                  void *priv_data);
1436
1437
1438 static void invalid_block(ext2_filsys fs FSCK_ATTR((unused)), blk_t blk)
1439 {
1440         printf(_("Bad block %u out of range; ignored.\n"), blk);
1441         return;
1442 }
1443
1444 static void read_bad_blocks_file(e2fsck_t ctx, const char *bad_blocks_file,
1445                           int replace_bad_blocks)
1446 {
1447         ext2_filsys fs = ctx->fs;
1448         errcode_t       retval;
1449         badblocks_list  bb_list = 0;
1450         FILE            *f;
1451         char            buf[1024];
1452
1453         e2fsck_read_bitmaps(ctx);
1454
1455         /*
1456          * Make sure the bad block inode is sane.  If there are any
1457          * illegal blocks, clear them.
1458          */
1459         retval = ext2fs_block_iterate(fs, EXT2_BAD_INO, 0, 0,
1460                                       check_bb_inode_blocks, 0);
1461         if (retval) {
1462                 com_err("ext2fs_block_iterate", retval,
1463                         _("while sanity checking the bad blocks inode"));
1464                 goto fatal;
1465         }
1466
1467         /*
1468          * If we're appending to the bad blocks inode, read in the
1469          * current bad blocks.
1470          */
1471         if (!replace_bad_blocks) {
1472                 retval = ext2fs_read_bb_inode(fs, &bb_list);
1473                 if (retval) {
1474                         com_err("ext2fs_read_bb_inode", retval,
1475                                 _("while reading the bad blocks inode"));
1476                         goto fatal;
1477                 }
1478         }
1479
1480         /*
1481          * Now read in the bad blocks from the file; if
1482          * bad_blocks_file is null, then try to run the badblocks
1483          * command.
1484          */
1485         if (bad_blocks_file) {
1486                 f = fopen(bad_blocks_file, "r");
1487                 if (!f) {
1488                         com_err("read_bad_blocks_file", errno,
1489                                 _("while trying to open %s"), bad_blocks_file);
1490                         goto fatal;
1491                 }
1492         } else {
1493                 sprintf(buf, "badblocks -b %d %s%s%s %d", fs->blocksize,
1494                         (ctx->options & E2F_OPT_PREEN) ? "" : "-s ",
1495                         (ctx->options & E2F_OPT_WRITECHECK) ? "-n " : "",
1496                         fs->device_name, fs->super->s_blocks_count);
1497                 f = popen(buf, "r");
1498                 if (!f) {
1499                         com_err("read_bad_blocks_file", errno,
1500                                 _("while trying popen '%s'"), buf);
1501                         goto fatal;
1502                 }
1503         }
1504         retval = ext2fs_read_bb_FILE(fs, f, &bb_list, invalid_block);
1505         if (bad_blocks_file)
1506                 fclose(f);
1507         else
1508                 pclose(f);
1509         if (retval) {
1510                 com_err("ext2fs_read_bb_FILE", retval,
1511                         _("while reading in list of bad blocks from file"));
1512                 goto fatal;
1513         }
1514
1515         /*
1516          * Finally, update the bad blocks from the bad_block_map
1517          */
1518         retval = ext2fs_update_bb_inode(fs, bb_list);
1519         if (retval) {
1520                 com_err("ext2fs_update_bb_inode", retval,
1521                         _("while updating bad block inode"));
1522                 goto fatal;
1523         }
1524
1525         ext2fs_badblocks_list_free(bb_list);
1526         return;
1527
1528 fatal:
1529         ctx->flags |= E2F_FLAG_ABORT;
1530         return;
1531
1532 }
1533
1534 static int check_bb_inode_blocks(ext2_filsys fs,
1535                                  blk_t *block_nr,
1536                                  int blockcnt FSCK_ATTR((unused)),
1537                                  void *priv_data FSCK_ATTR((unused)))
1538 {
1539         if (!*block_nr)
1540                 return 0;
1541
1542         /*
1543          * If the block number is outrageous, clear it and ignore it.
1544          */
1545         if (*block_nr >= fs->super->s_blocks_count ||
1546             *block_nr < fs->super->s_first_data_block) {
1547                 printf(_("Warning illegal block %u found in bad block inode.  Cleared.\n"), *block_nr);
1548                 *block_nr = 0;
1549                 return BLOCK_CHANGED;
1550         }
1551
1552         return 0;
1553 }
1554
1555 /*
1556  * Dictionary Abstract Data Type
1557  */
1558
1559
1560 /*
1561  * These macros provide short convenient names for structure members,
1562  * which are embellished with dict_ prefixes so that they are
1563  * properly confined to the documented namespace. It's legal for a
1564  * program which uses dict to define, for instance, a macro called ``parent''.
1565  * Such a macro would interfere with the dnode_t struct definition.
1566  * In general, highly portable and reusable C modules which expose their
1567  * structures need to confine structure member names to well-defined spaces.
1568  * The resulting identifiers aren't necessarily convenient to use, nor
1569  * readable, in the implementation, however!
1570  */
1571
1572 #define left dict_left
1573 #define right dict_right
1574 #define parent dict_parent
1575 #define color dict_color
1576 #define key dict_key
1577 #define data dict_data
1578
1579 #define nilnode dict_nilnode
1580 #define maxcount dict_maxcount
1581 #define compare dict_compare
1582 #define dupes dict_dupes
1583
1584 #define dict_root(D) ((D)->nilnode.left)
1585 #define dict_nil(D) (&(D)->nilnode)
1586 #define DICT_DEPTH_MAX 64
1587
1588 static void dnode_free(dnode_t *node);
1589
1590 /*
1591  * Perform a ``left rotation'' adjustment on the tree.  The given node P and
1592  * its right child C are rearranged so that the P instead becomes the left
1593  * child of C.   The left subtree of C is inherited as the new right subtree
1594  * for P.  The ordering of the keys within the tree is thus preserved.
1595  */
1596
1597 static void rotate_left(dnode_t *upper)
1598 {
1599     dnode_t *lower, *lowleft, *upparent;
1600
1601     lower = upper->right;
1602     upper->right = lowleft = lower->left;
1603     lowleft->parent = upper;
1604
1605     lower->parent = upparent = upper->parent;
1606
1607     /* don't need to check for root node here because root->parent is
1608        the sentinel nil node, and root->parent->left points back to root */
1609
1610     if (upper == upparent->left) {
1611         upparent->left = lower;
1612     } else {
1613         assert (upper == upparent->right);
1614         upparent->right = lower;
1615     }
1616
1617     lower->left = upper;
1618     upper->parent = lower;
1619 }
1620
1621 /*
1622  * This operation is the ``mirror'' image of rotate_left. It is
1623  * the same procedure, but with left and right interchanged.
1624  */
1625
1626 static void rotate_right(dnode_t *upper)
1627 {
1628     dnode_t *lower, *lowright, *upparent;
1629
1630     lower = upper->left;
1631     upper->left = lowright = lower->right;
1632     lowright->parent = upper;
1633
1634     lower->parent = upparent = upper->parent;
1635
1636     if (upper == upparent->right) {
1637         upparent->right = lower;
1638     } else {
1639         assert (upper == upparent->left);
1640         upparent->left = lower;
1641     }
1642
1643     lower->right = upper;
1644     upper->parent = lower;
1645 }
1646
1647 /*
1648  * Do a postorder traversal of the tree rooted at the specified
1649  * node and free everything under it.  Used by dict_free().
1650  */
1651
1652 static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
1653 {
1654     if (node == nil)
1655         return;
1656     free_nodes(dict, node->left, nil);
1657     free_nodes(dict, node->right, nil);
1658     dict->dict_freenode(node);
1659 }
1660
1661 /*
1662  * Verify that the tree contains the given node. This is done by
1663  * traversing all of the nodes and comparing their pointers to the
1664  * given pointer. Returns 1 if the node is found, otherwise
1665  * returns zero. It is intended for debugging purposes.
1666  */
1667
1668 static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
1669 {
1670     if (root != nil) {
1671         return root == node
1672                 || verify_dict_has_node(nil, root->left, node)
1673                 || verify_dict_has_node(nil, root->right, node);
1674     }
1675     return 0;
1676 }
1677
1678
1679 /*
1680  * Select a different set of node allocator routines.
1681  */
1682
1683 static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
1684 {
1685     assert (dict_count(dict) == 0);
1686     dict->dict_freenode = fr;
1687 }
1688
1689 /*
1690  * Free all the nodes in the dictionary by using the dictionary's
1691  * installed free routine. The dictionary is emptied.
1692  */
1693
1694 static void dict_free_nodes(dict_t *dict)
1695 {
1696     dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
1697     free_nodes(dict, root, nil);
1698     dict->dict_nodecount = 0;
1699     dict->nilnode.left = &dict->nilnode;
1700     dict->nilnode.right = &dict->nilnode;
1701 }
1702
1703 /*
1704  * Initialize a user-supplied dictionary object.
1705  */
1706
1707 static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
1708 {
1709     dict->compare = comp;
1710     dict->dict_freenode = dnode_free;
1711     dict->dict_nodecount = 0;
1712     dict->maxcount = maxcount;
1713     dict->nilnode.left = &dict->nilnode;
1714     dict->nilnode.right = &dict->nilnode;
1715     dict->nilnode.parent = &dict->nilnode;
1716     dict->nilnode.color = dnode_black;
1717     dict->dupes = 0;
1718     return dict;
1719 }
1720
1721 /*
1722  * Locate a node in the dictionary having the given key.
1723  * If the node is not found, a null a pointer is returned (rather than
1724  * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
1725  * located node is returned.
1726  */
1727
1728 static dnode_t *dict_lookup(dict_t *dict, const void *key)
1729 {
1730     dnode_t *root = dict_root(dict);
1731     dnode_t *nil = dict_nil(dict);
1732     dnode_t *saved;
1733     int result;
1734
1735     /* simple binary search adapted for trees that contain duplicate keys */
1736
1737     while (root != nil) {
1738         result = dict->compare(key, root->key);
1739         if (result < 0)
1740             root = root->left;
1741         else if (result > 0)
1742             root = root->right;
1743         else {
1744             if (!dict->dupes) { /* no duplicates, return match          */
1745                 return root;
1746             } else {            /* could be dupes, find leftmost one    */
1747                 do {
1748                     saved = root;
1749                     root = root->left;
1750                     while (root != nil && dict->compare(key, root->key))
1751                         root = root->right;
1752                 } while (root != nil);
1753                 return saved;
1754             }
1755         }
1756     }
1757
1758     return NULL;
1759 }
1760
1761 /*
1762  * Insert a node into the dictionary. The node should have been
1763  * initialized with a data field. All other fields are ignored.
1764  * The behavior is undefined if the user attempts to insert into
1765  * a dictionary that is already full (for which the dict_isfull()
1766  * function returns true).
1767  */
1768
1769 static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
1770 {
1771     dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
1772     dnode_t *parent = nil, *uncle, *grandpa;
1773     int result = -1;
1774
1775     node->key = key;
1776
1777     /* basic binary tree insert */
1778
1779     while (where != nil) {
1780         parent = where;
1781         result = dict->compare(key, where->key);
1782         /* trap attempts at duplicate key insertion unless it's explicitly allowed */
1783         assert (dict->dupes || result != 0);
1784         if (result < 0)
1785             where = where->left;
1786         else
1787             where = where->right;
1788     }
1789
1790     assert (where == nil);
1791
1792     if (result < 0)
1793         parent->left = node;
1794     else
1795         parent->right = node;
1796
1797     node->parent = parent;
1798     node->left = nil;
1799     node->right = nil;
1800
1801     dict->dict_nodecount++;
1802
1803     /* red black adjustments */
1804
1805     node->color = dnode_red;
1806
1807     while (parent->color == dnode_red) {
1808         grandpa = parent->parent;
1809         if (parent == grandpa->left) {
1810             uncle = grandpa->right;
1811             if (uncle->color == dnode_red) {    /* red parent, red uncle */
1812                 parent->color = dnode_black;
1813                 uncle->color = dnode_black;
1814                 grandpa->color = dnode_red;
1815                 node = grandpa;
1816                 parent = grandpa->parent;
1817             } else {                            /* red parent, black uncle */
1818                 if (node == parent->right) {
1819                     rotate_left(parent);
1820                     parent = node;
1821                     assert (grandpa == parent->parent);
1822                     /* rotation between parent and child preserves grandpa */
1823                 }
1824                 parent->color = dnode_black;
1825                 grandpa->color = dnode_red;
1826                 rotate_right(grandpa);
1827                 break;
1828             }
1829         } else {        /* symmetric cases: parent == parent->parent->right */
1830             uncle = grandpa->left;
1831             if (uncle->color == dnode_red) {
1832                 parent->color = dnode_black;
1833                 uncle->color = dnode_black;
1834                 grandpa->color = dnode_red;
1835                 node = grandpa;
1836                 parent = grandpa->parent;
1837             } else {
1838                 if (node == parent->left) {
1839                     rotate_right(parent);
1840                     parent = node;
1841                     assert (grandpa == parent->parent);
1842                 }
1843                 parent->color = dnode_black;
1844                 grandpa->color = dnode_red;
1845                 rotate_left(grandpa);
1846                 break;
1847             }
1848         }
1849     }
1850
1851     dict_root(dict)->color = dnode_black;
1852
1853 }
1854
1855 /*
1856  * Allocate a node using the dictionary's allocator routine, give it
1857  * the data item.
1858  */
1859
1860 static dnode_t *dnode_init(dnode_t *dnode, void *data)
1861 {
1862     dnode->data = data;
1863     dnode->parent = NULL;
1864     dnode->left = NULL;
1865     dnode->right = NULL;
1866     return dnode;
1867 }
1868
1869 static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
1870 {
1871     dnode_t *node = malloc(sizeof(dnode_t));
1872
1873     if (node) {
1874         dnode_init(node, data);
1875         dict_insert(dict, node, key);
1876         return 1;
1877     }
1878     return 0;
1879 }
1880
1881 /*
1882  * Return the node with the lowest (leftmost) key. If the dictionary is empty
1883  * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
1884  */
1885
1886 static dnode_t *dict_first(dict_t *dict)
1887 {
1888     dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
1889
1890     if (root != nil)
1891         while ((left = root->left) != nil)
1892             root = left;
1893
1894     return (root == nil) ? NULL : root;
1895 }
1896
1897 /*
1898  * Return the given node's successor node---the node which has the
1899  * next key in the the left to right ordering. If the node has
1900  * no successor, a null pointer is returned rather than a pointer to
1901  * the nil node.
1902  */
1903
1904 static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
1905 {
1906     dnode_t *nil = dict_nil(dict), *parent, *left;
1907
1908     if (curr->right != nil) {
1909         curr = curr->right;
1910         while ((left = curr->left) != nil)
1911             curr = left;
1912         return curr;
1913     }
1914
1915     parent = curr->parent;
1916
1917     while (parent != nil && curr == parent->right) {
1918         curr = parent;
1919         parent = curr->parent;
1920     }
1921
1922     return (parent == nil) ? NULL : parent;
1923 }
1924
1925
1926 static void dnode_free(dnode_t *node)
1927 {
1928     free(node);
1929 }
1930
1931
1932 #undef left
1933 #undef right
1934 #undef parent
1935 #undef color
1936 #undef key
1937 #undef data
1938
1939 #undef nilnode
1940 #undef maxcount
1941 #undef compare
1942 #undef dupes
1943
1944
1945 /*
1946  * dirinfo.c --- maintains the directory information table for e2fsck.
1947  */
1948
1949 /*
1950  * This subroutine is called during pass1 to create a directory info
1951  * entry.  During pass1, the passed-in parent is 0; it will get filled
1952  * in during pass2.
1953  */
1954 static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
1955 {
1956         struct dir_info *dir;
1957         int             i, j;
1958         ext2_ino_t      num_dirs;
1959         errcode_t       retval;
1960         unsigned long   old_size;
1961
1962 #if 0
1963         printf("add_dir_info for inode %lu...\n", ino);
1964 #endif
1965         if (!ctx->dir_info) {
1966                 ctx->dir_info_count = 0;
1967                 retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
1968                 if (retval)
1969                         num_dirs = 1024;        /* Guess */
1970                 ctx->dir_info_size = num_dirs + 10;
1971                 ctx->dir_info  = (struct dir_info *)
1972                         e2fsck_allocate_memory(ctx, ctx->dir_info_size
1973                                                * sizeof (struct dir_info),
1974                                                "directory map");
1975         }
1976
1977         if (ctx->dir_info_count >= ctx->dir_info_size) {
1978                 old_size = ctx->dir_info_size * sizeof(struct dir_info);
1979                 ctx->dir_info_size += 10;
1980                 retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
1981                                            sizeof(struct dir_info),
1982                                            &ctx->dir_info);
1983                 if (retval) {
1984                         ctx->dir_info_size -= 10;
1985                         return;
1986                 }
1987         }
1988
1989         /*
1990          * Normally, add_dir_info is called with each inode in
1991          * sequential order; but once in a while (like when pass 3
1992          * needs to recreate the root directory or lost+found
1993          * directory) it is called out of order.  In those cases, we
1994          * need to move the dir_info entries down to make room, since
1995          * the dir_info array needs to be sorted by inode number for
1996          * get_dir_info()'s sake.
1997          */
1998         if (ctx->dir_info_count &&
1999             ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
2000                 for (i = ctx->dir_info_count-1; i > 0; i--)
2001                         if (ctx->dir_info[i-1].ino < ino)
2002                                 break;
2003                 dir = &ctx->dir_info[i];
2004                 if (dir->ino != ino)
2005                         for (j = ctx->dir_info_count++; j > i; j--)
2006                                 ctx->dir_info[j] = ctx->dir_info[j-1];
2007         } else
2008                 dir = &ctx->dir_info[ctx->dir_info_count++];
2009
2010         dir->ino = ino;
2011         dir->dotdot = parent;
2012         dir->parent = parent;
2013 }
2014
2015 /*
2016  * get_dir_info() --- given an inode number, try to find the directory
2017  * information entry for it.
2018  */
2019 static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
2020 {
2021         int     low, high, mid;
2022
2023         low = 0;
2024         high = ctx->dir_info_count-1;
2025         if (!ctx->dir_info)
2026                 return 0;
2027         if (ino == ctx->dir_info[low].ino)
2028                 return &ctx->dir_info[low];
2029         if  (ino == ctx->dir_info[high].ino)
2030                 return &ctx->dir_info[high];
2031
2032         while (low < high) {
2033                 mid = (low+high)/2;
2034                 if (mid == low || mid == high)
2035                         break;
2036                 if (ino == ctx->dir_info[mid].ino)
2037                         return &ctx->dir_info[mid];
2038                 if (ino < ctx->dir_info[mid].ino)
2039                         high = mid;
2040                 else
2041                         low = mid;
2042         }
2043         return 0;
2044 }
2045
2046 /*
2047  * Free the dir_info structure when it isn't needed any more.
2048  */
2049 static void e2fsck_free_dir_info(e2fsck_t ctx)
2050 {
2051         if (ctx->dir_info) {
2052                 ext2fs_free_mem(&ctx->dir_info);
2053                 ctx->dir_info = 0;
2054         }
2055         ctx->dir_info_size = 0;
2056         ctx->dir_info_count = 0;
2057 }
2058
2059 /*
2060  * Return the count of number of directories in the dir_info structure
2061  */
2062 static inline int e2fsck_get_num_dirinfo(e2fsck_t ctx)
2063 {
2064         return ctx->dir_info_count;
2065 }
2066
2067 /*
2068  * A simple interator function
2069  */
2070 static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
2071 {
2072         if (*control >= ctx->dir_info_count)
2073                 return 0;
2074
2075         return(ctx->dir_info + (*control)++);
2076 }
2077
2078 /*
2079  * dirinfo.c --- maintains the directory information table for e2fsck.
2080  *
2081  */
2082
2083 #ifdef ENABLE_HTREE
2084
2085 /*
2086  * This subroutine is called during pass1 to create a directory info
2087  * entry.  During pass1, the passed-in parent is 0; it will get filled
2088  * in during pass2.
2089  */
2090 static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
2091 {
2092         struct dx_dir_info *dir;
2093         int             i, j;
2094         errcode_t       retval;
2095         unsigned long   old_size;
2096
2097 #if 0
2098         printf("add_dx_dir_info for inode %lu...\n", ino);
2099 #endif
2100         if (!ctx->dx_dir_info) {
2101                 ctx->dx_dir_info_count = 0;
2102                 ctx->dx_dir_info_size = 100; /* Guess */
2103                 ctx->dx_dir_info  = (struct dx_dir_info *)
2104                         e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
2105                                                * sizeof (struct dx_dir_info),
2106                                                "directory map");
2107         }
2108
2109         if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
2110                 old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
2111                 ctx->dx_dir_info_size += 10;
2112                 retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
2113                                            sizeof(struct dx_dir_info),
2114                                            &ctx->dx_dir_info);
2115                 if (retval) {
2116                         ctx->dx_dir_info_size -= 10;
2117                         return;
2118                 }
2119         }
2120
2121         /*
2122          * Normally, add_dx_dir_info is called with each inode in
2123          * sequential order; but once in a while (like when pass 3
2124          * needs to recreate the root directory or lost+found
2125          * directory) it is called out of order.  In those cases, we
2126          * need to move the dx_dir_info entries down to make room, since
2127          * the dx_dir_info array needs to be sorted by inode number for
2128          * get_dx_dir_info()'s sake.
2129          */
2130         if (ctx->dx_dir_info_count &&
2131             ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
2132                 for (i = ctx->dx_dir_info_count-1; i > 0; i--)
2133                         if (ctx->dx_dir_info[i-1].ino < ino)
2134                                 break;
2135                 dir = &ctx->dx_dir_info[i];
2136                 if (dir->ino != ino)
2137                         for (j = ctx->dx_dir_info_count++; j > i; j--)
2138                                 ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
2139         } else
2140                 dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
2141
2142         dir->ino = ino;
2143         dir->numblocks = num_blocks;
2144         dir->hashversion = 0;
2145         dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
2146                                        * sizeof (struct dx_dirblock_info),
2147                                        "dx_block info array");
2148
2149 }
2150
2151 /*
2152  * get_dx_dir_info() --- given an inode number, try to find the directory
2153  * information entry for it.
2154  */
2155 static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
2156 {
2157         int     low, high, mid;
2158
2159         low = 0;
2160         high = ctx->dx_dir_info_count-1;
2161         if (!ctx->dx_dir_info)
2162                 return 0;
2163         if (ino == ctx->dx_dir_info[low].ino)
2164                 return &ctx->dx_dir_info[low];
2165         if  (ino == ctx->dx_dir_info[high].ino)
2166                 return &ctx->dx_dir_info[high];
2167
2168         while (low < high) {
2169                 mid = (low+high)/2;
2170                 if (mid == low || mid == high)
2171                         break;
2172                 if (ino == ctx->dx_dir_info[mid].ino)
2173                         return &ctx->dx_dir_info[mid];
2174                 if (ino < ctx->dx_dir_info[mid].ino)
2175                         high = mid;
2176                 else
2177                         low = mid;
2178         }
2179         return 0;
2180 }
2181
2182 /*
2183  * Free the dx_dir_info structure when it isn't needed any more.
2184  */
2185 static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
2186 {
2187         int     i;
2188         struct dx_dir_info *dir;
2189
2190         if (ctx->dx_dir_info) {
2191                 dir = ctx->dx_dir_info;
2192                 for (i=0; i < ctx->dx_dir_info_count; i++) {
2193                         if (dir->dx_block) {
2194                                 ext2fs_free_mem(&dir->dx_block);
2195                                 dir->dx_block = 0;
2196                         }
2197                 }
2198                 ext2fs_free_mem(&ctx->dx_dir_info);
2199                 ctx->dx_dir_info = 0;
2200         }
2201         ctx->dx_dir_info_size = 0;
2202         ctx->dx_dir_info_count = 0;
2203 }
2204
2205 /*
2206  * A simple interator function
2207  */
2208 static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
2209 {
2210         if (*control >= ctx->dx_dir_info_count)
2211                 return 0;
2212
2213         return(ctx->dx_dir_info + (*control)++);
2214 }
2215
2216 #endif /* ENABLE_HTREE */
2217 /*
2218  * e2fsck.c - a consistency checker for the new extended file system.
2219  *
2220  */
2221
2222 /*
2223  * This function allocates an e2fsck context
2224  */
2225 static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
2226 {
2227         e2fsck_t        context;
2228         errcode_t       retval;
2229
2230         retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
2231         if (retval)
2232                 return retval;
2233
2234         memset(context, 0, sizeof(struct e2fsck_struct));
2235
2236         context->process_inode_size = 256;
2237         context->ext_attr_ver = 2;
2238
2239         *ret = context;
2240         return 0;
2241 }
2242
2243 struct ea_refcount_el {
2244         blk_t   ea_blk;
2245         int     ea_count;
2246 };
2247
2248 struct ea_refcount {
2249         blk_t           count;
2250         blk_t           size;
2251         blk_t           cursor;
2252         struct ea_refcount_el   *list;
2253 };
2254
2255 static void ea_refcount_free(ext2_refcount_t refcount)
2256 {
2257         if (!refcount)
2258                 return;
2259
2260         if (refcount->list)
2261                 ext2fs_free_mem(&refcount->list);
2262         ext2fs_free_mem(&refcount);
2263 }
2264
2265 /*
2266  * This function resets an e2fsck context; it is called when e2fsck
2267  * needs to be restarted.
2268  */
2269 static errcode_t e2fsck_reset_context(e2fsck_t ctx)
2270 {
2271         ctx->flags = 0;
2272         ctx->lost_and_found = 0;
2273         ctx->bad_lost_and_found = 0;
2274         if (ctx->inode_used_map) {
2275                 ext2fs_free_inode_bitmap(ctx->inode_used_map);
2276                 ctx->inode_used_map = 0;
2277         }
2278         if (ctx->inode_dir_map) {
2279                 ext2fs_free_inode_bitmap(ctx->inode_dir_map);
2280                 ctx->inode_dir_map = 0;
2281         }
2282         if (ctx->inode_reg_map) {
2283                 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
2284                 ctx->inode_reg_map = 0;
2285         }
2286         if (ctx->block_found_map) {
2287                 ext2fs_free_block_bitmap(ctx->block_found_map);
2288                 ctx->block_found_map = 0;
2289         }
2290         if (ctx->inode_link_info) {
2291                 ext2fs_free_icount(ctx->inode_link_info);
2292                 ctx->inode_link_info = 0;
2293         }
2294         if (ctx->journal_io) {
2295                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
2296                         io_channel_close(ctx->journal_io);
2297                 ctx->journal_io = 0;
2298         }
2299         if (ctx->fs && ctx->fs->dblist) {
2300                 ext2fs_free_dblist(ctx->fs->dblist);
2301                 ctx->fs->dblist = 0;
2302         }
2303         e2fsck_free_dir_info(ctx);
2304 #ifdef ENABLE_HTREE
2305         e2fsck_free_dx_dir_info(ctx);
2306 #endif
2307         if (ctx->refcount) {
2308                 ea_refcount_free(ctx->refcount);
2309                 ctx->refcount = 0;
2310         }
2311         if (ctx->refcount_extra) {
2312                 ea_refcount_free(ctx->refcount_extra);
2313                 ctx->refcount_extra = 0;
2314         }
2315         if (ctx->block_dup_map) {
2316                 ext2fs_free_block_bitmap(ctx->block_dup_map);
2317                 ctx->block_dup_map = 0;
2318         }
2319         if (ctx->block_ea_map) {
2320                 ext2fs_free_block_bitmap(ctx->block_ea_map);
2321                 ctx->block_ea_map = 0;
2322         }
2323         if (ctx->inode_bb_map) {
2324                 ext2fs_free_inode_bitmap(ctx->inode_bb_map);
2325                 ctx->inode_bb_map = 0;
2326         }
2327         if (ctx->inode_bad_map) {
2328                 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
2329                 ctx->inode_bad_map = 0;
2330         }
2331         if (ctx->inode_imagic_map) {
2332                 ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
2333                 ctx->inode_imagic_map = 0;
2334         }
2335         if (ctx->dirs_to_hash) {
2336                 ext2fs_u32_list_free(ctx->dirs_to_hash);
2337                 ctx->dirs_to_hash = 0;
2338         }
2339
2340         /*
2341          * Clear the array of invalid meta-data flags
2342          */
2343         if (ctx->invalid_inode_bitmap_flag) {
2344                 ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
2345                 ctx->invalid_inode_bitmap_flag = 0;
2346         }
2347         if (ctx->invalid_block_bitmap_flag) {
2348                 ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
2349                 ctx->invalid_block_bitmap_flag = 0;
2350         }
2351         if (ctx->invalid_inode_table_flag) {
2352                 ext2fs_free_mem(&ctx->invalid_inode_table_flag);
2353                 ctx->invalid_inode_table_flag = 0;
2354         }
2355
2356         /* Clear statistic counters */
2357         ctx->fs_directory_count = 0;
2358         ctx->fs_regular_count = 0;
2359         ctx->fs_blockdev_count = 0;
2360         ctx->fs_chardev_count = 0;
2361         ctx->fs_links_count = 0;
2362         ctx->fs_symlinks_count = 0;
2363         ctx->fs_fast_symlinks_count = 0;
2364         ctx->fs_fifo_count = 0;
2365         ctx->fs_total_count = 0;
2366         ctx->fs_badblocks_count = 0;
2367         ctx->fs_sockets_count = 0;
2368         ctx->fs_ind_count = 0;
2369         ctx->fs_dind_count = 0;
2370         ctx->fs_tind_count = 0;
2371         ctx->fs_fragmented = 0;
2372         ctx->large_files = 0;
2373
2374         /* Reset the superblock to the user's requested value */
2375         ctx->superblock = ctx->use_superblock;
2376
2377         return 0;
2378 }
2379
2380 static void e2fsck_free_context(e2fsck_t ctx)
2381 {
2382         if (!ctx)
2383                 return;
2384
2385         e2fsck_reset_context(ctx);
2386         if (ctx->blkid)
2387                 blkid_put_cache(ctx->blkid);
2388
2389         ext2fs_free_mem(&ctx);
2390 }
2391
2392 /*
2393  * ea_refcount.c
2394  */
2395
2396 /*
2397  * The strategy we use for keeping track of EA refcounts is as
2398  * follows.  We keep a sorted array of first EA blocks and its
2399  * reference counts.  Once the refcount has dropped to zero, it is
2400  * removed from the array to save memory space.  Once the EA block is
2401  * checked, its bit is set in the block_ea_map bitmap.
2402  */
2403
2404
2405 static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
2406 {
2407         ext2_refcount_t refcount;
2408         errcode_t       retval;
2409         size_t          bytes;
2410
2411         retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
2412         if (retval)
2413                 return retval;
2414         memset(refcount, 0, sizeof(struct ea_refcount));
2415
2416         if (!size)
2417                 size = 500;
2418         refcount->size = size;
2419         bytes = (size_t) (size * sizeof(struct ea_refcount_el));
2420 #ifdef DEBUG
2421         printf("Refcount allocated %d entries, %d bytes.\n",
2422                refcount->size, bytes);
2423 #endif
2424         retval = ext2fs_get_mem(bytes, &refcount->list);
2425         if (retval)
2426                 goto errout;
2427         memset(refcount->list, 0, bytes);
2428
2429         refcount->count = 0;
2430         refcount->cursor = 0;
2431
2432         *ret = refcount;
2433         return 0;
2434
2435 errout:
2436         ea_refcount_free(refcount);
2437         return(retval);
2438 }
2439
2440 /*
2441  * collapse_refcount() --- go through the refcount array, and get rid
2442  * of any count == zero entries
2443  */
2444 static void refcount_collapse(ext2_refcount_t refcount)
2445 {
2446         unsigned int    i, j;
2447         struct ea_refcount_el   *list;
2448
2449         list = refcount->list;
2450         for (i = 0, j = 0; i < refcount->count; i++) {
2451                 if (list[i].ea_count) {
2452                         if (i != j)
2453                                 list[j] = list[i];
2454                         j++;
2455                 }
2456         }
2457 #if defined(DEBUG) || defined(TEST_PROGRAM)
2458         printf("Refcount_collapse: size was %d, now %d\n",
2459                refcount->count, j);
2460 #endif
2461         refcount->count = j;
2462 }
2463
2464
2465 /*
2466  * insert_refcount_el() --- Insert a new entry into the sorted list at a
2467  *      specified position.
2468  */
2469 static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
2470                                                  blk_t blk, int pos)
2471 {
2472         struct ea_refcount_el   *el;
2473         errcode_t               retval;
2474         blk_t                   new_size = 0;
2475         int                     num;
2476
2477         if (refcount->count >= refcount->size) {
2478                 new_size = refcount->size + 100;
2479 #ifdef DEBUG
2480                 printf("Reallocating refcount %d entries...\n", new_size);
2481 #endif
2482                 retval = ext2fs_resize_mem((size_t) refcount->size *
2483                                            sizeof(struct ea_refcount_el),
2484                                            (size_t) new_size *
2485                                            sizeof(struct ea_refcount_el),
2486                                            &refcount->list);
2487                 if (retval)
2488                         return 0;
2489                 refcount->size = new_size;
2490         }
2491         num = (int) refcount->count - pos;
2492         if (num < 0)
2493                 return 0;       /* should never happen */
2494         if (num) {
2495                 memmove(&refcount->list[pos+1], &refcount->list[pos],
2496                         sizeof(struct ea_refcount_el) * num);
2497         }
2498         refcount->count++;
2499         el = &refcount->list[pos];
2500         el->ea_count = 0;
2501         el->ea_blk = blk;
2502         return el;
2503 }
2504
2505
2506 /*
2507  * get_refcount_el() --- given an block number, try to find refcount
2508  *      information in the sorted list.  If the create flag is set,
2509  *      and we can't find an entry, create one in the sorted list.
2510  */
2511 static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
2512                                               blk_t blk, int create)
2513 {
2514         float   range;
2515         int     low, high, mid;
2516         blk_t   lowval, highval;
2517
2518         if (!refcount || !refcount->list)
2519                 return 0;
2520 retry:
2521         low = 0;
2522         high = (int) refcount->count-1;
2523         if (create && ((refcount->count == 0) ||
2524                        (blk > refcount->list[high].ea_blk))) {
2525                 if (refcount->count >= refcount->size)
2526                         refcount_collapse(refcount);
2527
2528                 return insert_refcount_el(refcount, blk,
2529                                           (unsigned) refcount->count);
2530         }
2531         if (refcount->count == 0)
2532                 return 0;
2533
2534         if (refcount->cursor >= refcount->count)
2535                 refcount->cursor = 0;
2536         if (blk == refcount->list[refcount->cursor].ea_blk)
2537                 return &refcount->list[refcount->cursor++];
2538 #ifdef DEBUG
2539         printf("Non-cursor get_refcount_el: %u\n", blk);
2540 #endif
2541         while (low <= high) {
2542 #if 0
2543                 mid = (low+high)/2;
2544 #else
2545                 if (low == high)
2546                         mid = low;
2547                 else {
2548                         /* Interpolate for efficiency */
2549                         lowval = refcount->list[low].ea_blk;
2550                         highval = refcount->list[high].ea_blk;
2551
2552                         if (blk < lowval)
2553                                 range = 0;
2554                         else if (blk > highval)
2555                                 range = 1;
2556                         else
2557                                 range = ((float) (blk - lowval)) /
2558                                         (highval - lowval);
2559                         mid = low + ((int) (range * (high-low)));
2560                 }
2561 #endif
2562                 if (blk == refcount->list[mid].ea_blk) {
2563                         refcount->cursor = mid+1;
2564                         return &refcount->list[mid];
2565                 }
2566                 if (blk < refcount->list[mid].ea_blk)
2567                         high = mid-1;
2568                 else
2569                         low = mid+1;
2570         }
2571         /*
2572          * If we need to create a new entry, it should be right at
2573          * low (where high will be left at low-1).
2574          */
2575         if (create) {
2576                 if (refcount->count >= refcount->size) {
2577                         refcount_collapse(refcount);
2578                         if (refcount->count < refcount->size)
2579                                 goto retry;
2580                 }
2581                 return insert_refcount_el(refcount, blk, low);
2582         }
2583         return 0;
2584 }
2585
2586 static errcode_t
2587 ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
2588 {
2589         struct ea_refcount_el   *el;
2590
2591         el = get_refcount_el(refcount, blk, 1);
2592         if (!el)
2593                 return EXT2_ET_NO_MEMORY;
2594         el->ea_count++;
2595
2596         if (ret)
2597                 *ret = el->ea_count;
2598         return 0;
2599 }
2600
2601 static errcode_t
2602 ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
2603 {
2604         struct ea_refcount_el   *el;
2605
2606         el = get_refcount_el(refcount, blk, 0);
2607         if (!el || el->ea_count == 0)
2608                 return EXT2_ET_INVALID_ARGUMENT;
2609
2610         el->ea_count--;
2611
2612         if (ret)
2613                 *ret = el->ea_count;
2614         return 0;
2615 }
2616
2617 static errcode_t
2618 ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
2619 {
2620         struct ea_refcount_el   *el;
2621
2622         /*
2623          * Get the refcount element
2624          */
2625         el = get_refcount_el(refcount, blk, count ? 1 : 0);
2626         if (!el)
2627                 return count ? EXT2_ET_NO_MEMORY : 0;
2628         el->ea_count = count;
2629         return 0;
2630 }
2631
2632 static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
2633 {
2634         refcount->cursor = 0;
2635 }
2636
2637
2638 static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
2639 {
2640         struct ea_refcount_el   *list;
2641
2642         while (1) {
2643                 if (refcount->cursor >= refcount->count)
2644                         return 0;
2645                 list = refcount->list;
2646                 if (list[refcount->cursor].ea_count) {
2647                         if (ret)
2648                                 *ret = list[refcount->cursor].ea_count;
2649                         return list[refcount->cursor++].ea_blk;
2650                 }
2651                 refcount->cursor++;
2652         }
2653 }
2654
2655
2656 /*
2657  * ehandler.c --- handle bad block errors which come up during the
2658  *      course of an e2fsck session.
2659  */
2660
2661
2662 static const char *operation;
2663
2664 static errcode_t
2665 e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
2666                          void *data, size_t size FSCK_ATTR((unused)),
2667                          int actual FSCK_ATTR((unused)), errcode_t error)
2668 {
2669         int     i;
2670         char    *p;
2671         ext2_filsys fs = (ext2_filsys) channel->app_data;
2672         e2fsck_t ctx;
2673
2674         ctx = (e2fsck_t) fs->priv_data;
2675
2676         /*
2677          * If more than one block was read, try reading each block
2678          * separately.  We could use the actual bytes read to figure
2679          * out where to start, but we don't bother.
2680          */
2681         if (count > 1) {
2682                 p = (char *) data;
2683                 for (i=0; i < count; i++, p += channel->block_size, block++) {
2684                         error = io_channel_read_blk(channel, block,
2685                                                     1, p);
2686                         if (error)
2687                                 return error;
2688                 }
2689                 return 0;
2690         }
2691         if (operation)
2692                 printf(_("Error reading block %lu (%s) while %s.  "), block,
2693                        error_message(error), operation);
2694         else
2695                 printf(_("Error reading block %lu (%s).  "), block,
2696                        error_message(error));
2697         preenhalt(ctx);
2698         if (ask(ctx, _("Ignore error"), 1)) {
2699                 if (ask(ctx, _("Force rewrite"), 1))
2700                         io_channel_write_blk(channel, block, 1, data);
2701                 return 0;
2702         }
2703
2704         return error;
2705 }
2706
2707 static errcode_t
2708 e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
2709                         const void *data, size_t size FSCK_ATTR((unused)),
2710                         int actual FSCK_ATTR((unused)), errcode_t error)
2711 {
2712         int             i;
2713         const char      *p;
2714         ext2_filsys fs = (ext2_filsys) channel->app_data;
2715         e2fsck_t ctx;
2716
2717         ctx = (e2fsck_t) fs->priv_data;
2718
2719         /*
2720          * If more than one block was written, try writing each block
2721          * separately.  We could use the actual bytes read to figure
2722          * out where to start, but we don't bother.
2723          */
2724         if (count > 1) {
2725                 p = (const char *) data;
2726                 for (i=0; i < count; i++, p += channel->block_size, block++) {
2727                         error = io_channel_write_blk(channel, block,
2728                                                      1, p);
2729                         if (error)
2730                                 return error;
2731                 }
2732                 return 0;
2733         }
2734
2735         if (operation)
2736                 printf(_("Error writing block %lu (%s) while %s.  "), block,
2737                        error_message(error), operation);
2738         else
2739                 printf(_("Error writing block %lu (%s).  "), block,
2740                        error_message(error));
2741         preenhalt(ctx);
2742         if (ask(ctx, _("Ignore error"), 1))
2743                 return 0;
2744
2745         return error;
2746 }
2747
2748 static inline const char *ehandler_operation(const char *op)
2749 {
2750         const char *ret = operation;
2751
2752         operation = op;
2753         return ret;
2754 }
2755
2756 static void ehandler_init(io_channel channel)
2757 {
2758         channel->read_error = e2fsck_handle_read_error;
2759         channel->write_error = e2fsck_handle_write_error;
2760 }
2761
2762 /*
2763  * journal.c --- code for handling the "ext3" journal
2764  *
2765  * Copyright (C) 2000 Andreas Dilger
2766  * Copyright (C) 2000 Theodore Ts'o
2767  *
2768  * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
2769  * Copyright (C) 1999 Red Hat Software
2770  *
2771  * This file may be redistributed under the terms of the
2772  * GNU General Public License version 2 or at your discretion
2773  * any later version.
2774  */
2775
2776 #define MNT_FL (MS_MGC_VAL | MS_RDONLY)
2777
2778
2779 #ifdef __CONFIG_JBD_DEBUG__E2FS         /* Enabled by configure --enable-jfs-debug */
2780 static int bh_count = 0;
2781 #endif
2782
2783 /*
2784  * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
2785  * This creates a larger static binary, and a smaller binary using
2786  * shared libraries.  It's also probably slightly less CPU-efficient,
2787  * which is why it's not on by default.  But, it's a good way of
2788  * testing the functions in inode_io.c and fileio.c.
2789  */
2790 #undef USE_INODE_IO
2791
2792 /* Kernel compatibility functions for handling the journal.  These allow us
2793  * to use the recovery.c file virtually unchanged from the kernel, so we
2794  * don't have to do much to keep kernel and user recovery in sync.
2795  */
2796 static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
2797 {
2798 #ifdef USE_INODE_IO
2799         *phys = block;
2800         return 0;
2801 #else
2802         struct inode    *inode = journal->j_inode;
2803         errcode_t       retval;
2804         blk_t           pblk;
2805
2806         if (!inode) {
2807                 *phys = block;
2808                 return 0;
2809         }
2810
2811         retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
2812                             &inode->i_ext2, NULL, 0, block, &pblk);
2813         *phys = pblk;
2814         return (retval);
2815 #endif
2816 }
2817
2818 static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
2819 {
2820         struct buffer_head *bh;
2821
2822         bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
2823         if (!bh)
2824                 return NULL;
2825
2826         jfs_debug(4, "getblk for block %lu (%d bytes)(total %d)\n",
2827                   (unsigned long) blocknr, blocksize, ++bh_count);
2828
2829         bh->b_ctx = kdev->k_ctx;
2830         if (kdev->k_dev == K_DEV_FS)
2831                 bh->b_io = kdev->k_ctx->fs->io;
2832         else
2833                 bh->b_io = kdev->k_ctx->journal_io;
2834         bh->b_size = blocksize;
2835         bh->b_blocknr = blocknr;
2836
2837         return bh;
2838 }
2839
2840 static void sync_blockdev(kdev_t kdev)
2841 {
2842         io_channel      io;
2843
2844         if (kdev->k_dev == K_DEV_FS)
2845                 io = kdev->k_ctx->fs->io;
2846         else
2847                 io = kdev->k_ctx->journal_io;
2848
2849         io_channel_flush(io);
2850 }
2851
2852 static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
2853 {
2854         int retval;
2855         struct buffer_head *bh;
2856
2857         for (; nr > 0; --nr) {
2858                 bh = *bhp++;
2859                 if (rw == READ && !bh->b_uptodate) {
2860                         jfs_debug(3, "reading block %lu/%p\n",
2861                                   (unsigned long) bh->b_blocknr, (void *) bh);
2862                         retval = io_channel_read_blk(bh->b_io,
2863                                                      bh->b_blocknr,
2864                                                      1, bh->b_data);
2865                         if (retval) {
2866                                 com_err(bh->b_ctx->device_name, retval,
2867                                         "while reading block %lu\n",
2868                                         (unsigned long) bh->b_blocknr);
2869                                 bh->b_err = retval;
2870                                 continue;
2871                         }
2872                         bh->b_uptodate = 1;
2873                 } else if (rw == WRITE && bh->b_dirty) {
2874                         jfs_debug(3, "writing block %lu/%p\n",
2875                                   (unsigned long) bh->b_blocknr, (void *) bh);
2876                         retval = io_channel_write_blk(bh->b_io,
2877                                                       bh->b_blocknr,
2878                                                       1, bh->b_data);
2879                         if (retval) {
2880                                 com_err(bh->b_ctx->device_name, retval,
2881                                         "while writing block %lu\n",
2882                                         (unsigned long) bh->b_blocknr);
2883                                 bh->b_err = retval;
2884                                 continue;
2885                         }
2886                         bh->b_dirty = 0;
2887                         bh->b_uptodate = 1;
2888                 } else {
2889                         jfs_debug(3, "no-op %s for block %lu\n",
2890                                   rw == READ ? "read" : "write",
2891                                   (unsigned long) bh->b_blocknr);
2892                 }
2893         }
2894 }
2895
2896 static inline void mark_buffer_dirty(struct buffer_head *bh)
2897 {
2898         bh->b_dirty = 1;
2899 }
2900
2901 static inline void mark_buffer_clean(struct buffer_head * bh)
2902 {
2903         bh->b_dirty = 0;
2904 }
2905
2906 static void brelse(struct buffer_head *bh)
2907 {
2908         if (bh->b_dirty)
2909                 ll_rw_block(WRITE, 1, &bh);
2910         jfs_debug(3, "freeing block %lu/%p (total %d)\n",
2911                   (unsigned long) bh->b_blocknr, (void *) bh, --bh_count);
2912         ext2fs_free_mem(&bh);
2913 }
2914
2915 static inline int buffer_uptodate(struct buffer_head *bh)
2916 {
2917         return bh->b_uptodate;
2918 }
2919
2920 static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
2921 {
2922         bh->b_uptodate = val;
2923 }
2924
2925 static void wait_on_buffer(struct buffer_head *bh)
2926 {
2927         if (!bh->b_uptodate)
2928                 ll_rw_block(READ, 1, &bh);
2929 }
2930
2931
2932 static void e2fsck_clear_recover(e2fsck_t ctx, int error)
2933 {
2934         ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
2935
2936         /* if we had an error doing journal recovery, we need a full fsck */
2937         if (error)
2938                 ctx->fs->super->s_state &= ~EXT2_VALID_FS;
2939         ext2fs_mark_super_dirty(ctx->fs);
2940 }
2941
2942 static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
2943 {
2944         struct ext2_super_block *sb = ctx->fs->super;
2945         struct ext2_super_block jsuper;
2946         struct problem_context  pctx;
2947         struct buffer_head      *bh;
2948         struct inode            *j_inode = NULL;
2949         struct kdev_s           *dev_fs = NULL, *dev_journal;
2950         const char              *journal_name = 0;
2951         journal_t               *journal = NULL;
2952         errcode_t               retval = 0;
2953         io_manager              io_ptr = 0;
2954         unsigned long           start = 0;
2955         blk_t                   blk;
2956         int                     ext_journal = 0;
2957         int                     tried_backup_jnl = 0;
2958         int                     i;
2959
2960         clear_problem_context(&pctx);
2961
2962         journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
2963         if (!journal) {
2964                 return EXT2_ET_NO_MEMORY;
2965         }
2966
2967         dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
2968         if (!dev_fs) {
2969                 retval = EXT2_ET_NO_MEMORY;
2970                 goto errout;
2971         }
2972         dev_journal = dev_fs+1;
2973
2974         dev_fs->k_ctx = dev_journal->k_ctx = ctx;
2975         dev_fs->k_dev = K_DEV_FS;
2976         dev_journal->k_dev = K_DEV_JOURNAL;
2977
2978         journal->j_dev = dev_journal;
2979         journal->j_fs_dev = dev_fs;
2980         journal->j_inode = NULL;
2981         journal->j_blocksize = ctx->fs->blocksize;
2982
2983         if (uuid_is_null(sb->s_journal_uuid)) {
2984                 if (!sb->s_journal_inum)
2985                         return EXT2_ET_BAD_INODE_NUM;
2986                 j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
2987                                                  "journal inode");
2988                 if (!j_inode) {
2989                         retval = EXT2_ET_NO_MEMORY;
2990                         goto errout;
2991                 }
2992
2993                 j_inode->i_ctx = ctx;
2994                 j_inode->i_ino = sb->s_journal_inum;
2995
2996                 if ((retval = ext2fs_read_inode(ctx->fs,
2997                                                 sb->s_journal_inum,
2998                                                 &j_inode->i_ext2))) {
2999                 try_backup_journal:
3000                         if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
3001                             tried_backup_jnl)
3002                                 goto errout;
3003                         memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
3004                         memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
3005                                EXT2_N_BLOCKS*4);
3006                         j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
3007                         j_inode->i_ext2.i_links_count = 1;
3008                         j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
3009                         tried_backup_jnl++;
3010                 }
3011                 if (!j_inode->i_ext2.i_links_count ||
3012                     !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
3013                         retval = EXT2_ET_NO_JOURNAL;
3014                         goto try_backup_journal;
3015                 }
3016                 if (j_inode->i_ext2.i_size / journal->j_blocksize <
3017                     JFS_MIN_JOURNAL_BLOCKS) {
3018                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
3019                         goto try_backup_journal;
3020                 }
3021                 for (i=0; i < EXT2_N_BLOCKS; i++) {
3022                         blk = j_inode->i_ext2.i_block[i];
3023                         if (!blk) {
3024                                 if (i < EXT2_NDIR_BLOCKS) {
3025                                         retval = EXT2_ET_JOURNAL_TOO_SMALL;
3026                                         goto try_backup_journal;
3027                                 }
3028                                 continue;
3029                         }
3030                         if (blk < sb->s_first_data_block ||
3031                             blk >= sb->s_blocks_count) {
3032                                 retval = EXT2_ET_BAD_BLOCK_NUM;
3033                                 goto try_backup_journal;
3034                         }
3035                 }
3036                 journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
3037
3038 #ifdef USE_INODE_IO
3039                 retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
3040                                                  &j_inode->i_ext2,
3041                                                  &journal_name);
3042                 if (retval)
3043                         goto errout;
3044
3045                 io_ptr = inode_io_manager;
3046 #else
3047                 journal->j_inode = j_inode;
3048                 ctx->journal_io = ctx->fs->io;
3049                 if ((retval = journal_bmap(journal, 0, &start)) != 0)
3050                         goto errout;
3051 #endif
3052         } else {
3053                 ext_journal = 1;
3054                 if (!ctx->journal_name) {
3055                         char uuid[37];
3056
3057                         uuid_unparse(sb->s_journal_uuid, uuid);
3058                         ctx->journal_name = blkid_get_devname(ctx->blkid,
3059                                                               "UUID", uuid);
3060                         if (!ctx->journal_name)
3061                                 ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
3062                 }
3063                 journal_name = ctx->journal_name;
3064
3065                 if (!journal_name) {
3066                         fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
3067                         return EXT2_ET_LOAD_EXT_JOURNAL;
3068                 }
3069
3070                 jfs_debug(1, "Using journal file %s\n", journal_name);
3071                 io_ptr = unix_io_manager;
3072         }
3073
3074 #if 0
3075         test_io_backing_manager = io_ptr;
3076         io_ptr = test_io_manager;
3077 #endif
3078 #ifndef USE_INODE_IO
3079         if (ext_journal)
3080 #endif
3081                 retval = io_ptr->open(journal_name, IO_FLAG_RW,
3082                                       &ctx->journal_io);
3083         if (retval)
3084                 goto errout;
3085
3086         io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
3087
3088         if (ext_journal) {
3089                 if (ctx->fs->blocksize == 1024)
3090                         start = 1;
3091                 bh = getblk(dev_journal, start, ctx->fs->blocksize);
3092                 if (!bh) {
3093                         retval = EXT2_ET_NO_MEMORY;
3094                         goto errout;
3095                 }
3096                 ll_rw_block(READ, 1, &bh);
3097                 if ((retval = bh->b_err) != 0)
3098                         goto errout;
3099                 memcpy(&jsuper, start ? bh->b_data :  bh->b_data + 1024,
3100                        sizeof(jsuper));
3101                 brelse(bh);
3102 #ifdef EXT2FS_ENABLE_SWAPFS
3103                 if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
3104                         ext2fs_swap_super(&jsuper);
3105 #endif
3106                 if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
3107                     !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
3108                         fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
3109                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
3110                         goto errout;
3111                 }
3112                 /* Make sure the journal UUID is correct */
3113                 if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
3114                            sizeof(jsuper.s_uuid))) {
3115                         fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
3116                         retval = EXT2_ET_LOAD_EXT_JOURNAL;
3117                         goto errout;
3118                 }
3119
3120                 journal->j_maxlen = jsuper.s_blocks_count;
3121                 start++;
3122         }
3123
3124         if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
3125                 retval = EXT2_ET_NO_MEMORY;
3126                 goto errout;
3127         }
3128
3129         journal->j_sb_buffer = bh;
3130         journal->j_superblock = (journal_superblock_t *)bh->b_data;
3131
3132 #ifdef USE_INODE_IO
3133         if (j_inode)
3134                 ext2fs_free_mem(&j_inode);
3135 #endif
3136
3137         *ret_journal = journal;
3138         return 0;
3139
3140 errout:
3141         if (dev_fs)
3142                 ext2fs_free_mem(&dev_fs);
3143         if (j_inode)
3144                 ext2fs_free_mem(&j_inode);
3145         if (journal)
3146                 ext2fs_free_mem(&journal);
3147         return retval;
3148
3149 }
3150
3151 static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
3152                                               struct problem_context *pctx)
3153 {
3154         struct ext2_super_block *sb = ctx->fs->super;
3155         int recover = ctx->fs->super->s_feature_incompat &
3156                 EXT3_FEATURE_INCOMPAT_RECOVER;
3157         int has_journal = ctx->fs->super->s_feature_compat &
3158                 EXT3_FEATURE_COMPAT_HAS_JOURNAL;
3159
3160         if (has_journal || sb->s_journal_inum) {
3161                 /* The journal inode is bogus, remove and force full fsck */
3162                 pctx->ino = sb->s_journal_inum;
3163                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
3164                         if (has_journal && sb->s_journal_inum)
3165                                 printf("*** ext3 journal has been deleted - "
3166                                        "filesystem is now ext2 only ***\n\n");
3167                         sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
3168                         sb->s_journal_inum = 0;
3169                         ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
3170                         e2fsck_clear_recover(ctx, 1);
3171                         return 0;
3172                 }
3173                 return EXT2_ET_BAD_INODE_NUM;
3174         } else if (recover) {
3175                 if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
3176                         e2fsck_clear_recover(ctx, 1);
3177                         return 0;
3178                 }
3179                 return EXT2_ET_UNSUPP_FEATURE;
3180         }
3181         return 0;
3182 }
3183
3184 #define V1_SB_SIZE      0x0024
3185 static void clear_v2_journal_fields(journal_t *journal)
3186 {
3187         e2fsck_t ctx = journal->j_dev->k_ctx;
3188         struct problem_context pctx;
3189
3190         clear_problem_context(&pctx);
3191
3192         if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
3193                 return;
3194
3195         memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
3196                ctx->fs->blocksize-V1_SB_SIZE);
3197         mark_buffer_dirty(journal->j_sb_buffer);
3198 }
3199
3200
3201 static errcode_t e2fsck_journal_load(journal_t *journal)
3202 {
3203         e2fsck_t ctx = journal->j_dev->k_ctx;
3204         journal_superblock_t *jsb;
3205         struct buffer_head *jbh = journal->j_sb_buffer;
3206         struct problem_context pctx;
3207
3208         clear_problem_context(&pctx);
3209
3210         ll_rw_block(READ, 1, &jbh);
3211         if (jbh->b_err) {
3212                 com_err(ctx->device_name, jbh->b_err,
3213                         _("reading journal superblock\n"));
3214                 return jbh->b_err;
3215         }
3216
3217         jsb = journal->j_superblock;
3218         /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
3219         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
3220                 return e2fsck_journal_fix_bad_inode(ctx, &pctx);
3221
3222         switch (ntohl(jsb->s_header.h_blocktype)) {
3223         case JFS_SUPERBLOCK_V1:
3224                 journal->j_format_version = 1;
3225                 if (jsb->s_feature_compat ||
3226                     jsb->s_feature_incompat ||
3227                     jsb->s_feature_ro_compat ||
3228                     jsb->s_nr_users)
3229                         clear_v2_journal_fields(journal);
3230                 break;
3231
3232         case JFS_SUPERBLOCK_V2:
3233                 journal->j_format_version = 2;
3234                 if (ntohl(jsb->s_nr_users) > 1 &&
3235                     uuid_is_null(ctx->fs->super->s_journal_uuid))
3236                         clear_v2_journal_fields(journal);
3237                 if (ntohl(jsb->s_nr_users) > 1) {
3238                         fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
3239                         return EXT2_ET_JOURNAL_UNSUPP_VERSION;
3240                 }
3241                 break;
3242
3243         /*
3244          * These should never appear in a journal super block, so if
3245          * they do, the journal is badly corrupted.
3246          */
3247         case JFS_DESCRIPTOR_BLOCK:
3248         case JFS_COMMIT_BLOCK:
3249         case JFS_REVOKE_BLOCK:
3250                 return EXT2_ET_CORRUPT_SUPERBLOCK;
3251
3252         /* If we don't understand the superblock major type, but there
3253          * is a magic number, then it is likely to be a new format we
3254          * just don't understand, so leave it alone. */
3255         default:
3256                 return EXT2_ET_JOURNAL_UNSUPP_VERSION;
3257         }
3258
3259         if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
3260                 return EXT2_ET_UNSUPP_FEATURE;
3261
3262         if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
3263                 return EXT2_ET_RO_UNSUPP_FEATURE;
3264
3265         /* We have now checked whether we know enough about the journal
3266          * format to be able to proceed safely, so any other checks that
3267          * fail we should attempt to recover from. */
3268         if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
3269                 com_err(ctx->program_name, EXT2_ET_CORRUPT_SUPERBLOCK,
3270                         _("%s: no valid journal superblock found\n"),
3271                         ctx->device_name);
3272                 return EXT2_ET_CORRUPT_SUPERBLOCK;
3273         }
3274
3275         if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
3276                 journal->j_maxlen = ntohl(jsb->s_maxlen);
3277         else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
3278                 com_err(ctx->program_name, EXT2_ET_CORRUPT_SUPERBLOCK,
3279                         _("%s: journal too short\n"),
3280                         ctx->device_name);
3281                 return EXT2_ET_CORRUPT_SUPERBLOCK;
3282         }
3283
3284         journal->j_tail_sequence = ntohl(jsb->s_sequence);
3285         journal->j_transaction_sequence = journal->j_tail_sequence;
3286         journal->j_tail = ntohl(jsb->s_start);
3287         journal->j_first = ntohl(jsb->s_first);
3288         journal->j_last = ntohl(jsb->s_maxlen);
3289
3290         return 0;
3291 }
3292
3293 static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
3294                                        journal_t *journal)
3295 {
3296         char *p;
3297         union {
3298                 uuid_t uuid;
3299                 __u32 val[4];
3300         } u;
3301         __u32 new_seq = 0;
3302         int i;
3303
3304         /* Leave a valid existing V1 superblock signature alone.
3305          * Anything unrecognisable we overwrite with a new V2
3306          * signature. */
3307
3308         if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
3309             jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
3310                 jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
3311                 jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
3312         }
3313
3314         /* Zero out everything else beyond the superblock header */
3315
3316         p = ((char *) jsb) + sizeof(journal_header_t);
3317         memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
3318
3319         jsb->s_blocksize = htonl(ctx->fs->blocksize);
3320         jsb->s_maxlen = htonl(journal->j_maxlen);
3321         jsb->s_first = htonl(1);
3322
3323         /* Initialize the journal sequence number so that there is "no"
3324          * chance we will find old "valid" transactions in the journal.
3325          * This avoids the need to zero the whole journal (slow to do,
3326          * and risky when we are just recovering the filesystem).
3327          */
3328         uuid_generate(u.uuid);
3329         for (i = 0; i < 4; i ++)
3330                 new_seq ^= u.val[i];
3331         jsb->s_sequence = htonl(new_seq);
3332
3333         mark_buffer_dirty(journal->j_sb_buffer);
3334         ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
3335 }
3336
3337 static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
3338                                                   journal_t *journal,
3339                                                   struct problem_context *pctx)
3340 {
3341         struct ext2_super_block *sb = ctx->fs->super;
3342         int recover = ctx->fs->super->s_feature_incompat &
3343                 EXT3_FEATURE_INCOMPAT_RECOVER;
3344
3345         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
3346                 if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
3347                         e2fsck_journal_reset_super(ctx, journal->j_superblock,
3348                                                    journal);
3349                         journal->j_transaction_sequence = 1;
3350                         e2fsck_clear_recover(ctx, recover);
3351                         return 0;
3352                 }
3353                 return EXT2_ET_CORRUPT_SUPERBLOCK;
3354         } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
3355                 return EXT2_ET_CORRUPT_SUPERBLOCK;
3356
3357         return 0;
3358 }
3359
3360 static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
3361                                    int reset, int drop)
3362 {
3363         journal_superblock_t *jsb;
3364
3365         if (drop)
3366                 mark_buffer_clean(journal->j_sb_buffer);
3367         else if (!(ctx->options & E2F_OPT_READONLY)) {
3368                 jsb = journal->j_superblock;
3369                 jsb->s_sequence = htonl(journal->j_transaction_sequence);
3370                 if (reset)
3371                         jsb->s_start = 0; /* this marks the journal as empty */
3372                 mark_buffer_dirty(journal->j_sb_buffer);
3373         }
3374         brelse(journal->j_sb_buffer);
3375
3376         if (ctx->journal_io) {
3377                 if (ctx->fs && ctx->fs->io != ctx->journal_io)
3378                         io_channel_close(ctx->journal_io);
3379                 ctx->journal_io = 0;
3380         }
3381
3382 #ifndef USE_INODE_IO
3383         if (journal->j_inode)
3384                 ext2fs_free_mem(&journal->j_inode);
3385 #endif
3386         if (journal->j_fs_dev)
3387                 ext2fs_free_mem(&journal->j_fs_dev);
3388         ext2fs_free_mem(&journal);
3389 }
3390
3391 /*
3392  * This function makes sure that the superblock fields regarding the
3393  * journal are consistent.
3394  */
3395 static int e2fsck_check_ext3_journal(e2fsck_t ctx)
3396 {
3397         struct ext2_super_block *sb = ctx->fs->super;
3398         journal_t *journal;
3399         int recover = ctx->fs->super->s_feature_incompat &
3400                 EXT3_FEATURE_INCOMPAT_RECOVER;
3401         struct problem_context pctx;
3402         problem_t problem;
3403         int reset = 0, force_fsck = 0;
3404         int retval;
3405
3406         /* If we don't have any journal features, don't do anything more */
3407         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
3408             !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
3409             uuid_is_null(sb->s_journal_uuid))
3410                 return 0;
3411
3412         clear_problem_context(&pctx);
3413         pctx.num = sb->s_journal_inum;
3414
3415         retval = e2fsck_get_journal(ctx, &journal);
3416         if (retval) {
3417                 if ((retval == EXT2_ET_BAD_INODE_NUM) ||
3418                     (retval == EXT2_ET_BAD_BLOCK_NUM) ||
3419                     (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
3420                     (retval == EXT2_ET_NO_JOURNAL))
3421                         return e2fsck_journal_fix_bad_inode(ctx, &pctx);
3422                 return retval;
3423         }
3424
3425         retval = e2fsck_journal_load(journal);
3426         if (retval) {
3427                 if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
3428                     ((retval == EXT2_ET_UNSUPP_FEATURE) &&
3429                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
3430                                   &pctx))) ||
3431                     ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
3432                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
3433                                   &pctx))) ||
3434                     ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
3435                     (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
3436                         retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
3437                                                                   &pctx);
3438                 e2fsck_journal_release(ctx, journal, 0, 1);
3439                 return retval;
3440         }
3441
3442         /*
3443          * We want to make the flags consistent here.  We will not leave with
3444          * needs_recovery set but has_journal clear.  We can't get in a loop
3445          * with -y, -n, or -p, only if a user isn't making up their mind.
3446          */
3447 no_has_journal:
3448         if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
3449                 recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
3450                 pctx.str = "inode";
3451                 if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
3452                         if (recover &&
3453                             !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
3454                                 goto no_has_journal;
3455                         /*
3456                          * Need a full fsck if we are releasing a
3457                          * journal stored on a reserved inode.
3458                          */
3459                         force_fsck = recover ||
3460                                 (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
3461                         /* Clear all of the journal fields */
3462                         sb->s_journal_inum = 0;
3463                         sb->s_journal_dev = 0;
3464                         memset(sb->s_journal_uuid, 0,
3465                                sizeof(sb->s_journal_uuid));
3466                         e2fsck_clear_recover(ctx, force_fsck);
3467                 } else if (!(ctx->options & E2F_OPT_READONLY)) {
3468                         sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
3469                         ext2fs_mark_super_dirty(ctx->fs);
3470                 }
3471         }
3472
3473         if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
3474             !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
3475             journal->j_superblock->s_start != 0) {
3476                 /* Print status information */
3477                 fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
3478                 if (ctx->superblock)
3479                         problem = PR_0_JOURNAL_RUN_DEFAULT;
3480                 else
3481                         problem = PR_0_JOURNAL_RUN;
3482                 if (fix_problem(ctx, problem, &pctx)) {
3483                         ctx->options |= E2F_OPT_FORCE;
3484                         sb->s_feature_incompat |=
3485                                 EXT3_FEATURE_INCOMPAT_RECOVER;
3486                         ext2fs_mark_super_dirty(ctx->fs);
3487                 } else if (fix_problem(ctx,
3488                                        PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
3489                         reset = 1;
3490                         sb->s_state &= ~EXT2_VALID_FS;
3491                         ext2fs_mark_super_dirty(ctx->fs);
3492                 }
3493                 /*
3494                  * If the user answers no to the above question, we
3495                  * ignore the fact that journal apparently has data;
3496                  * accidentally replaying over valid data would be far
3497                  * worse than skipping a questionable recovery.
3498                  *
3499                  * XXX should we abort with a fatal error here?  What
3500                  * will the ext3 kernel code do if a filesystem with
3501                  * !NEEDS_RECOVERY but with a non-zero
3502                  * journal->j_superblock->s_start is mounted?
3503                  */
3504         }
3505
3506         e2fsck_journal_release(ctx, journal, reset, 0);
3507         return retval;
3508 }
3509
3510 static errcode_t recover_ext3_journal(e2fsck_t ctx)
3511 {
3512         journal_t *journal;
3513         int retval;
3514
3515         journal_init_revoke_caches();
3516         retval = e2fsck_get_journal(ctx, &journal);
3517         if (retval)
3518                 return retval;
3519
3520         retval = e2fsck_journal_load(journal);
3521         if (retval)
3522                 goto errout;
3523
3524         retval = journal_init_revoke(journal, 1024);
3525         if (retval)
3526                 goto errout;
3527
3528         retval = -journal_recover(journal);
3529         if (retval)
3530                 goto errout;
3531
3532         if (journal->j_superblock->s_errno) {
3533                 ctx->fs->super->s_state |= EXT2_ERROR_FS;
3534                 ext2fs_mark_super_dirty(ctx->fs);
3535                 journal->j_superblock->s_errno = 0;
3536                 mark_buffer_dirty(journal->j_sb_buffer);
3537         }
3538
3539 errout:
3540         journal_destroy_revoke(journal);
3541         journal_destroy_revoke_caches();
3542         e2fsck_journal_release(ctx, journal, 1, 0);
3543         return retval;
3544 }
3545
3546 static int e2fsck_run_ext3_journal(e2fsck_t ctx)
3547 {
3548         io_manager io_ptr = ctx->fs->io->manager;
3549         int blocksize = ctx->fs->blocksize;
3550         errcode_t       retval, recover_retval;
3551
3552         printf(_("%s: recovering journal\n"), ctx->device_name);
3553         if (ctx->options & E2F_OPT_READONLY) {
3554                 printf(_("%s: won't do journal recovery while read-only\n"),
3555                        ctx->device_name);
3556                 return EXT2_ET_FILE_RO;
3557         }
3558
3559         if (ctx->fs->flags & EXT2_FLAG_DIRTY)
3560                 ext2fs_flush(ctx->fs);  /* Force out any modifications */
3561
3562         recover_retval = recover_ext3_journal(ctx);
3563
3564         /*
3565          * Reload the filesystem context to get up-to-date data from disk
3566          * because journal recovery will change the filesystem under us.
3567          */
3568         ext2fs_close(ctx->fs);
3569         retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
3570                              ctx->superblock, blocksize, io_ptr,
3571                              &ctx->fs);
3572
3573         if (retval) {
3574                 com_err(ctx->program_name, retval,
3575                         _("while trying to re-open %s"),
3576                         ctx->device_name);
3577                 fatal_error(ctx, 0);
3578         }
3579         ctx->fs->priv_data = ctx;
3580
3581         /* Set the superblock flags */
3582         e2fsck_clear_recover(ctx, recover_retval);
3583         return recover_retval;
3584 }
3585
3586 /*
3587  * This function will move the journal inode from a visible file in
3588  * the filesystem directory hierarchy to the reserved inode if necessary.
3589  */
3590 static const char * const journal_names[] = {
3591         ".journal", "journal", ".journal.dat", "journal.dat", 0 };
3592
3593 static void e2fsck_move_ext3_journal(e2fsck_t ctx)
3594 {
3595         struct ext2_super_block *sb = ctx->fs->super;
3596         struct problem_context  pctx;
3597         struct ext2_inode       inode;
3598         ext2_filsys             fs = ctx->fs;
3599         ext2_ino_t              ino;
3600         errcode_t               retval;
3601         const char * const *    cpp;
3602         int                     group, mount_flags;
3603
3604         clear_problem_context(&pctx);
3605
3606         /*
3607          * If the filesystem is opened read-only, or there is no
3608          * journal, then do nothing.
3609          */
3610         if ((ctx->options & E2F_OPT_READONLY) ||
3611             (sb->s_journal_inum == 0) ||
3612             !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
3613                 return;
3614
3615         /*
3616          * Read in the journal inode
3617          */
3618         if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
3619                 return;
3620
3621         /*
3622          * If it's necessary to backup the journal inode, do so.
3623          */
3624         if ((sb->s_jnl_backup_type == 0) ||
3625             ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
3626              memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
3627                 if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
3628                         memcpy(sb->s_jnl_blocks, inode.i_block,
3629                                EXT2_N_BLOCKS*4);
3630                         sb->s_jnl_blocks[16] = inode.i_size;
3631                         sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
3632                         ext2fs_mark_super_dirty(fs);
3633                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
3634                 }
3635         }
3636
3637         /*
3638          * If the journal is already the hidden inode, then do nothing
3639          */
3640         if (sb->s_journal_inum == EXT2_JOURNAL_INO)
3641                 return;
3642
3643         /*
3644          * The journal inode had better have only one link and not be readable.
3645          */
3646         if (inode.i_links_count != 1)
3647                 return;
3648
3649         /*
3650          * If the filesystem is mounted, or we can't tell whether
3651          * or not it's mounted, do nothing.
3652          */
3653         retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
3654         if (retval || (mount_flags & EXT2_MF_MOUNTED))
3655                 return;
3656
3657         /*
3658          * If we can't find the name of the journal inode, then do
3659          * nothing.
3660          */
3661         for (cpp = journal_names; *cpp; cpp++) {
3662                 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
3663                                        strlen(*cpp), 0, &ino);
3664                 if ((retval == 0) && (ino == sb->s_journal_inum))
3665                         break;
3666         }
3667         if (*cpp == 0)
3668                 return;
3669
3670         /* We need the inode bitmap to be loaded */
3671         retval = ext2fs_read_bitmaps(fs);
3672         if (retval)
3673                 return;
3674
3675         pctx.str = *cpp;
3676         if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
3677                 return;
3678
3679         /*
3680          * OK, we've done all the checks, let's actually move the
3681          * journal inode.  Errors at this point mean we need to force
3682          * an ext2 filesystem check.
3683          */
3684         if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
3685                 goto err_out;
3686         if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
3687                 goto err_out;
3688         sb->s_journal_inum = EXT2_JOURNAL_INO;
3689         ext2fs_mark_super_dirty(fs);
3690         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
3691         inode.i_links_count = 0;
3692         inode.i_dtime = time(0);
3693         if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
3694                 goto err_out;
3695
3696         group = ext2fs_group_of_ino(fs, ino);
3697         ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
3698         ext2fs_mark_ib_dirty(fs);
3699         fs->group_desc[group].bg_free_inodes_count++;
3700         fs->super->s_free_inodes_count++;
3701         return;
3702
3703 err_out:
3704         pctx.errcode = retval;
3705         fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
3706         fs->super->s_state &= ~EXT2_VALID_FS;
3707         ext2fs_mark_super_dirty(fs);
3708         return;
3709 }
3710
3711 /*
3712  * message.c --- print e2fsck messages (with compression)
3713  *
3714  * print_e2fsck_message() prints a message to the user, using
3715  * compression techniques and expansions of abbreviations.
3716  *
3717  * The following % expansions are supported:
3718  *
3719  *      %b      <blk>                   block number
3720  *      %B      <blkcount>              integer
3721  *      %c      <blk2>                  block number
3722  *      %Di     <dirent>->ino           inode number
3723  *      %Dn     <dirent>->name          string
3724  *      %Dr     <dirent>->rec_len
3725  *      %Dl     <dirent>->name_len
3726  *      %Dt     <dirent>->filetype
3727  *      %d      <dir>                   inode number
3728  *      %g      <group>                 integer
3729  *      %i      <ino>                   inode number
3730  *      %Is     <inode> -> i_size
3731  *      %IS     <inode> -> i_extra_isize
3732  *      %Ib     <inode> -> i_blocks
3733  *      %Il     <inode> -> i_links_count
3734  *      %Im     <inode> -> i_mode
3735  *      %IM     <inode> -> i_mtime
3736  *      %IF     <inode> -> i_faddr
3737  *      %If     <inode> -> i_file_acl
3738  *      %Id     <inode> -> i_dir_acl
3739  *      %Iu     <inode> -> i_uid
3740  *      %Ig     <inode> -> i_gid
3741  *      %j      <ino2>                  inode number
3742  *      %m      <com_err error message>
3743  *      %N      <num>
3744  *      %p      ext2fs_get_pathname of directory <ino>
3745  *      %P      ext2fs_get_pathname of <dirent>->ino with <ino2> as
3746  *                      the containing directory.  (If dirent is NULL
3747  *                      then return the pathname of directory <ino2>)
3748  *      %q      ext2fs_get_pathname of directory <dir>
3749  *      %Q      ext2fs_get_pathname of directory <ino> with <dir> as
3750  *                      the containing directory.
3751  *      %s      <str>                   miscellaneous string
3752  *      %S      backup superblock
3753  *      %X      <num> hexadecimal format
3754  *
3755  * The following '@' expansions are supported:
3756  *
3757  *      @a      extended attribute
3758  *      @A      error allocating
3759  *      @b      block
3760  *      @B      bitmap
3761  *      @c      compress
3762  *      @C      conflicts with some other fs block
3763  *      @D      deleted
3764  *      @d      directory
3765  *      @e      entry
3766  *      @E      Entry '%Dn' in %p (%i)
3767  *      @f      filesystem
3768  *      @F      for @i %i (%Q) is
3769  *      @g      group
3770  *      @h      HTREE directory inode
3771  *      @i      inode
3772  *      @I      illegal
3773  *      @j      journal
3774  *      @l      lost+found
3775  *      @L      is a link
3776  *      @o      orphaned
3777  *      @p      problem in
3778  *      @r      root inode
3779  *      @s      should be
3780  *      @S      superblock
3781  *      @u      unattached
3782  *      @v      device
3783  *      @z      zero-length
3784  */
3785
3786
3787 /*
3788  * This structure defines the abbreviations used by the text strings
3789  * below.  The first character in the string is the index letter.  An
3790  * abbreviation of the form '@<i>' is expanded by looking up the index
3791  * letter <i> in the table below.
3792  */
3793 static const char * const abbrevs[] = {
3794         N_("aextended attribute"),
3795         N_("Aerror allocating"),
3796         N_("bblock"),
3797         N_("Bbitmap"),
3798         N_("ccompress"),
3799         N_("Cconflicts with some other fs @b"),
3800         N_("iinode"),
3801         N_("Iillegal"),
3802         N_("jjournal"),
3803         N_("Ddeleted"),
3804         N_("ddirectory"),
3805         N_("eentry"),
3806         N_("E@e '%Dn' in %p (%i)"),
3807         N_("ffilesystem"),
3808         N_("Ffor @i %i (%Q) is"),
3809         N_("ggroup"),
3810         N_("hHTREE @d @i"),
3811         N_("llost+found"),
3812         N_("Lis a link"),
3813         N_("oorphaned"),
3814         N_("pproblem in"),
3815         N_("rroot @i"),
3816         N_("sshould be"),
3817         N_("Ssuper@b"),
3818         N_("uunattached"),
3819         N_("vdevice"),
3820         N_("zzero-length"),
3821         "@@",
3822         0
3823         };
3824
3825 /*
3826  * Give more user friendly names to the "special" inodes.
3827  */
3828 #define num_special_inodes      11
3829 static const char * const special_inode_name[] =
3830 {
3831         N_("<The NULL inode>"),                 /* 0 */
3832         N_("<The bad blocks inode>"),           /* 1 */
3833         "/",                                    /* 2 */
3834         N_("<The ACL index inode>"),            /* 3 */
3835         N_("<The ACL data inode>"),             /* 4 */
3836         N_("<The boot loader inode>"),          /* 5 */
3837         N_("<The undelete directory inode>"),   /* 6 */
3838         N_("<The group descriptor inode>"),     /* 7 */
3839         N_("<The journal inode>"),              /* 8 */
3840         N_("<Reserved inode 9>"),               /* 9 */
3841         N_("<Reserved inode 10>"),              /* 10 */
3842 };
3843
3844 /*
3845  * This function does "safe" printing.  It will convert non-printable
3846  * ASCII characters using '^' and M- notation.
3847  */
3848 static void safe_print(const char *cp, int len)
3849 {
3850         unsigned char   ch;
3851
3852         if (len < 0)
3853                 len = strlen(cp);
3854
3855         while (len--) {
3856                 ch = *cp++;
3857                 if (ch > 128) {
3858                         fputs("M-", stdout);
3859                         ch -= 128;
3860                 }
3861                 if ((ch < 32) || (ch == 0x7f)) {
3862                         fputc('^', stdout);
3863                         ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
3864                 }
3865                 fputc(ch, stdout);
3866         }
3867 }
3868
3869
3870 /*
3871  * This function prints a pathname, using the ext2fs_get_pathname
3872  * function
3873  */
3874 static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
3875 {
3876         errcode_t       retval;
3877         char            *path;
3878
3879         if (!dir && (ino < num_special_inodes)) {
3880                 fputs(_(special_inode_name[ino]), stdout);
3881                 return;
3882         }
3883
3884         retval = ext2fs_get_pathname(fs, dir, ino, &path);
3885         if (retval)
3886                 fputs("???", stdout);
3887         else {
3888                 safe_print(path, -1);
3889                 ext2fs_free_mem(&path);
3890         }
3891 }
3892
3893 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
3894                           struct problem_context *pctx, int first);
3895 /*
3896  * This function handles the '@' expansion.  We allow recursive
3897  * expansion; an @ expression can contain further '@' and '%'
3898  * expressions.
3899  */
3900 static void expand_at_expression(e2fsck_t ctx, char ch,
3901                                           struct problem_context *pctx,
3902                                           int *first)
3903 {
3904         const char * const *cpp;
3905         const char *str;
3906
3907         /* Search for the abbreviation */
3908         for (cpp = abbrevs; *cpp; cpp++) {
3909                 if (ch == *cpp[0])
3910                         break;
3911         }
3912         if (*cpp) {
3913                 str = _(*cpp) + 1;
3914                 if (*first && islower(*str)) {
3915                         *first = 0;
3916                         fputc(toupper(*str++), stdout);
3917                 }
3918                 print_e2fsck_message(ctx, str, pctx, *first);
3919         } else
3920                 printf("@%c", ch);
3921 }
3922
3923 /*
3924  * This function expands '%IX' expressions
3925  */
3926 static void expand_inode_expression(char ch,
3927                                              struct problem_context *ctx)
3928 {
3929         struct ext2_inode       *inode;
3930         struct ext2_inode_large *large_inode;
3931         char *                  time_str;
3932         time_t                  t;
3933         int                     do_gmt = -1;
3934
3935         if (!ctx || !ctx->inode)
3936                 goto no_inode;
3937
3938         inode = ctx->inode;
3939         large_inode = (struct ext2_inode_large *) inode;
3940
3941         switch (ch) {
3942         case 's':
3943                 if (LINUX_S_ISDIR(inode->i_mode))
3944                         printf("%u", inode->i_size);
3945                 else {
3946 #ifdef EXT2_NO_64_TYPE
3947                         if (inode->i_size_high)
3948                                 printf("0x%x%08x", inode->i_size_high,
3949                                        inode->i_size);
3950                         else
3951                                 printf("%u", inode->i_size);
3952 #else
3953                         printf("%llu", (inode->i_size |
3954                                         ((__u64) inode->i_size_high << 32)));
3955 #endif
3956                 }
3957                 break;
3958         case 'S':
3959                 printf("%u", large_inode->i_extra_isize);
3960                 break;
3961         case 'b':
3962                 printf("%u", inode->i_blocks);
3963                 break;
3964         case 'l':
3965                 printf("%d", inode->i_links_count);
3966                 break;
3967         case 'm':
3968                 printf("0%o", inode->i_mode);
3969                 break;
3970         case 'M':
3971                 /* The diet libc doesn't respect the TZ environemnt variable */
3972                 if (do_gmt == -1) {
3973                         time_str = getenv("TZ");
3974                         if (!time_str)
3975                                 time_str = "";
3976                         do_gmt = !strcmp(time_str, "GMT");
3977                 }
3978                 t = inode->i_mtime;
3979                 time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
3980                 printf("%.24s", time_str);
3981                 break;
3982         case 'F':
3983                 printf("%u", inode->i_faddr);
3984                 break;
3985         case 'f':
3986                 printf("%u", inode->i_file_acl);
3987                 break;
3988         case 'd':
3989                 printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
3990                               inode->i_dir_acl : 0));
3991                 break;
3992         case 'u':
3993                 printf("%d", (inode->i_uid |
3994                               (inode->osd2.linux2.l_i_uid_high << 16)));
3995                 break;
3996         case 'g':
3997                 printf("%d", (inode->i_gid |
3998                               (inode->osd2.linux2.l_i_gid_high << 16)));
3999                 break;
4000         default:
4001         no_inode:
4002                 printf("%%I%c", ch);
4003                 break;
4004         }
4005 }
4006
4007 /*
4008  * This function expands '%dX' expressions
4009  */
4010 static _INLINE_ void expand_dirent_expression(char ch,
4011                                               struct problem_context *ctx)
4012 {
4013         struct ext2_dir_entry   *dirent;
4014         int     len;
4015
4016         if (!ctx || !ctx->dirent)
4017                 goto no_dirent;
4018
4019         dirent = ctx->dirent;
4020
4021         switch (ch) {
4022         case 'i':
4023                 printf("%u", dirent->inode);
4024                 break;
4025         case 'n':
4026                 len = dirent->name_len & 0xFF;
4027                 if (len > EXT2_NAME_LEN)
4028                         len = EXT2_NAME_LEN;
4029                 if (len > dirent->rec_len)
4030                         len = dirent->rec_len;
4031                 safe_print(dirent->name, len);
4032                 break;
4033         case 'r':
4034                 printf("%u", dirent->rec_len);
4035                 break;
4036         case 'l':
4037                 printf("%u", dirent->name_len & 0xFF);
4038                 break;
4039         case 't':
4040                 printf("%u", dirent->name_len >> 8);
4041                 break;
4042         default:
4043         no_dirent:
4044                 printf("%%D%c", ch);
4045                 break;
4046         }
4047 }
4048
4049 static _INLINE_ void expand_percent_expression(ext2_filsys fs, char ch,
4050                                                struct problem_context *ctx)
4051 {
4052         if (!ctx)
4053                 goto no_context;
4054
4055         switch (ch) {
4056         case '%':
4057                 fputc('%', stdout);
4058                 break;
4059         case 'b':
4060                 printf("%u", ctx->blk);
4061                 break;
4062         case 'B':
4063 #ifdef EXT2_NO_64_TYPE
4064                 printf("%d", ctx->blkcount);
4065 #else
4066                 printf("%lld", ctx->blkcount);
4067 #endif
4068                 break;
4069         case 'c':
4070                 printf("%u", ctx->blk2);
4071                 break;
4072         case 'd':
4073                 printf("%u", ctx->dir);
4074                 break;
4075         case 'g':
4076                 printf("%d", ctx->group);
4077                 break;
4078         case 'i':
4079                 printf("%u", ctx->ino);
4080                 break;
4081         case 'j':
4082                 printf("%u", ctx->ino2);
4083                 break;
4084         case 'm':
4085                 printf("%s", error_message(ctx->errcode));
4086                 break;
4087         case 'N':
4088 #ifdef EXT2_NO_64_TYPE
4089                 printf("%u", ctx->num);
4090 #else
4091                 printf("%llu", ctx->num);
4092 #endif
4093                 break;
4094         case 'p':
4095                 print_pathname(fs, ctx->ino, 0);
4096                 break;
4097         case 'P':
4098                 print_pathname(fs, ctx->ino2,
4099                                ctx->dirent ? ctx->dirent->inode : 0);
4100                 break;
4101         case 'q':
4102                 print_pathname(fs, ctx->dir, 0);
4103                 break;
4104         case 'Q':
4105                 print_pathname(fs, ctx->dir, ctx->ino);
4106                 break;
4107         case 'S':
4108                 printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
4109                 break;
4110         case 's':
4111                 printf("%s", ctx->str ? ctx->str : "NULL");
4112                 break;
4113         case 'X':
4114 #ifdef EXT2_NO_64_TYPE
4115                 printf("0x%x", ctx->num);
4116 #else
4117                 printf("0x%llx", ctx->num);
4118 #endif
4119                 break;
4120         default:
4121         no_context:
4122                 printf("%%%c", ch);
4123                 break;
4124         }
4125 }
4126
4127
4128 static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
4129                           struct problem_context *pctx, int first)
4130 {
4131         ext2_filsys fs = ctx->fs;
4132         const char *    cp;
4133         int             i;
4134
4135         e2fsck_clear_progbar(ctx);
4136         for (cp = msg; *cp; cp++) {
4137                 if (cp[0] == '@') {
4138                         cp++;
4139                         expand_at_expression(ctx, *cp, pctx, &first);
4140                 } else if (cp[0] == '%' && cp[1] == 'I') {
4141                         cp += 2;
4142                         expand_inode_expression(*cp, pctx);
4143                 } else if (cp[0] == '%' && cp[1] == 'D') {
4144                         cp += 2;
4145                         expand_dirent_expression(*cp, pctx);
4146                 } else if ((cp[0] == '%')) {
4147                         cp++;
4148                         expand_percent_expression(fs, *cp, pctx);
4149                 } else {
4150                         for (i=0; cp[i]; i++)
4151                                 if ((cp[i] == '@') || cp[i] == '%')
4152                                         break;
4153                         printf("%.*s", i, cp);
4154                         cp += i-1;
4155                 }
4156                 first = 0;
4157         }
4158 }
4159
4160
4161 /*
4162  * region.c --- code which manages allocations within a region.
4163  */
4164
4165 struct region_el {
4166         region_addr_t   start;
4167         region_addr_t   end;
4168         struct region_el *next;
4169 };
4170
4171 struct region_struct {
4172         region_addr_t   min;
4173         region_addr_t   max;
4174         struct region_el *allocated;
4175 };
4176
4177 static region_t region_create(region_addr_t min, region_addr_t max)
4178 {
4179         region_t        region;
4180
4181         region = malloc(sizeof(struct region_struct));
4182         if (!region)
4183                 return NULL;
4184         memset(region, 0, sizeof(struct region_struct));
4185         region->min = min;
4186         region->max = max;
4187         return region;
4188 }
4189
4190 static void region_free(region_t region)
4191 {
4192         struct region_el        *r, *next;
4193
4194         for (r = region->allocated; r; r = next) {
4195                 next = r->next;
4196                 free(r);
4197         }
4198         memset(region, 0, sizeof(struct region_struct));
4199         free(region);
4200 }
4201
4202 static int region_allocate(region_t region, region_addr_t start, int n)
4203 {
4204         struct region_el        *r, *new_region, *prev, *next;
4205         region_addr_t end;
4206
4207         end = start+n;
4208         if ((start < region->min) || (end > region->max))
4209                 return -1;
4210         if (n == 0)
4211                 return 1;
4212
4213         /*
4214          * Search through the linked list.  If we find that it
4215          * conflicts witih something that's already allocated, return
4216          * 1; if we can find an existing region which we can grow, do
4217          * so.  Otherwise, stop when we find the appropriate place
4218          * insert a new region element into the linked list.
4219          */
4220         for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
4221                 if (((start >= r->start) && (start < r->end)) ||
4222                     ((end > r->start) && (end <= r->end)) ||
4223                     ((start <= r->start) && (end >= r->end)))
4224                         return 1;
4225                 if (end == r->start) {
4226                         r->start = start;
4227                         return 0;
4228                 }
4229                 if (start == r->end) {
4230                         if ((next = r->next)) {
4231                                 if (end > next->start)
4232                                         return 1;
4233                                 if (end == next->start) {
4234                                         r->end = next->end;
4235                                         r->next = next->next;
4236                                         free(next);
4237                                         return 0;
4238                                 }
4239                         }
4240                         r->end = end;
4241                         return 0;
4242                 }
4243                 if (start < r->start)
4244                         break;
4245         }
4246         /*
4247          * Insert a new region element structure into the linked list
4248          */
4249         new_region = malloc(sizeof(struct region_el));
4250         if (!new_region)
4251                 return -1;
4252         new_region->start = start;
4253         new_region->end = start + n;
4254         new_region->next = r;
4255         if (prev)
4256                 prev->next = new_region;
4257         else
4258                 region->allocated = new_region;
4259         return 0;
4260 }
4261
4262 /*
4263  * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
4264  *
4265  * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
4266  * and applies the following tests to each inode:
4267  *
4268  *      - The mode field of the inode must be legal.
4269  *      - The size and block count fields of the inode are correct.
4270  *      - A data block must not be used by another inode
4271  *
4272  * Pass 1 also gathers the collects the following information:
4273  *
4274  *      - A bitmap of which inodes are in use.          (inode_used_map)
4275  *      - A bitmap of which inodes are directories.     (inode_dir_map)
4276  *      - A bitmap of which inodes are regular files.   (inode_reg_map)
4277  *      - A bitmap of which inodes have bad fields.     (inode_bad_map)
4278  *      - A bitmap of which inodes are in bad blocks.   (inode_bb_map)
4279  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
4280  *      - A bitmap of which blocks are in use.          (block_found_map)
4281  *      - A bitmap of which blocks are in use by two inodes     (block_dup_map)
4282  *      - The data blocks of the directory inodes.      (dir_map)
4283  *
4284  * Pass 1 is designed to stash away enough information so that the
4285  * other passes should not need to read in the inode information
4286  * during the normal course of a filesystem check.  (Althogh if an
4287  * inconsistency is detected, other passes may need to read in an
4288  * inode to fix it.)
4289  *
4290  * Note that pass 1B will be invoked if there are any duplicate blocks
4291  * found.
4292  */
4293
4294
4295 static int process_block(ext2_filsys fs, blk_t  *blocknr,
4296                          e2_blkcnt_t blockcnt, blk_t ref_blk,
4297                          int ref_offset, void *priv_data);
4298 static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
4299                              e2_blkcnt_t blockcnt, blk_t ref_blk,
4300                              int ref_offset, void *priv_data);
4301 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4302                          char *block_buf);
4303 static void mark_table_blocks(e2fsck_t ctx);
4304 static void alloc_bb_map(e2fsck_t ctx);
4305 static void alloc_imagic_map(e2fsck_t ctx);
4306 static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
4307 static void handle_fs_bad_blocks(e2fsck_t ctx);
4308 static void process_inodes(e2fsck_t ctx, char *block_buf);
4309 static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b);
4310 static errcode_t scan_callback(ext2_filsys fs, ext2_inode_scan scan,
4311                                   dgrp_t group, void * priv_data);
4312 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
4313                                     char *block_buf, int adjust_sign);
4314 /* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
4315
4316 static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
4317                                struct ext2_inode * inode, int bufsize,
4318                                const char *proc);
4319
4320 struct process_block_struct_1 {
4321         ext2_ino_t      ino;
4322         unsigned        is_dir:1, is_reg:1, clear:1, suppress:1,
4323                                 fragmented:1, compressed:1, bbcheck:1;
4324         blk_t           num_blocks;
4325         blk_t           max_blocks;
4326         e2_blkcnt_t     last_block;
4327         int             num_illegal_blocks;
4328         blk_t           previous_block;
4329         struct ext2_inode *inode;
4330         struct problem_context *pctx;
4331         ext2fs_block_bitmap fs_meta_blocks;
4332         e2fsck_t        ctx;
4333 };
4334
4335 struct process_inode_block {
4336         ext2_ino_t ino;
4337         struct ext2_inode inode;
4338 };
4339
4340 struct scan_callback_struct {
4341         e2fsck_t        ctx;
4342         char            *block_buf;
4343 };
4344
4345 /*
4346  * For the inodes to process list.
4347  */
4348 static struct process_inode_block *inodes_to_process;
4349 static int process_inode_count;
4350
4351 static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
4352                             EXT2_MIN_BLOCK_LOG_SIZE + 1];
4353
4354 /*
4355  * Free all memory allocated by pass1 in preparation for restarting
4356  * things.
4357  */
4358 static void unwind_pass1(void)
4359 {
4360         ext2fs_free_mem(&inodes_to_process);
4361         inodes_to_process = 0;
4362 }
4363
4364 /*
4365  * Check to make sure a device inode is real.  Returns 1 if the device
4366  * checks out, 0 if not.
4367  *
4368  * Note: this routine is now also used to check FIFO's and Sockets,
4369  * since they have the same requirement; the i_block fields should be
4370  * zero.
4371  */
4372 static int
4373 e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
4374 {
4375         int     i;
4376
4377         /*
4378          * If i_blocks is non-zero, or the index flag is set, then
4379          * this is a bogus device/fifo/socket
4380          */
4381         if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
4382             (inode->i_flags & EXT2_INDEX_FL))
4383                 return 0;
4384
4385         /*
4386          * We should be able to do the test below all the time, but
4387          * because the kernel doesn't forcibly clear the device
4388          * inode's additional i_block fields, there are some rare
4389          * occasions when a legitimate device inode will have non-zero
4390          * additional i_block fields.  So for now, we only complain
4391          * when the immutable flag is set, which should never happen
4392          * for devices.  (And that's when the problem is caused, since
4393          * you can't set or clear immutable flags for devices.)  Once
4394          * the kernel has been fixed we can change this...
4395          */
4396         if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
4397                 for (i=4; i < EXT2_N_BLOCKS; i++)
4398                         if (inode->i_block[i])
4399                                 return 0;
4400         }
4401         return 1;
4402 }
4403
4404 /*
4405  * Check to make sure a symlink inode is real.  Returns 1 if the symlink
4406  * checks out, 0 if not.
4407  */
4408 static int
4409 e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
4410 {
4411         unsigned int len;
4412         int i;
4413         blk_t   blocks;
4414
4415         if ((inode->i_size_high || inode->i_size == 0) ||
4416             (inode->i_flags & EXT2_INDEX_FL))
4417                 return 0;
4418
4419         blocks = ext2fs_inode_data_blocks(fs, inode);
4420         if (blocks) {
4421                 if ((inode->i_size >= fs->blocksize) ||
4422                     (blocks != fs->blocksize >> 9) ||
4423                     (inode->i_block[0] < fs->super->s_first_data_block) ||
4424                     (inode->i_block[0] >= fs->super->s_blocks_count))
4425                         return 0;
4426
4427                 for (i = 1; i < EXT2_N_BLOCKS; i++)
4428                         if (inode->i_block[i])
4429                                 return 0;
4430
4431                 if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
4432                         return 0;
4433
4434                 len = strnlen(buf, fs->blocksize);
4435                 if (len == fs->blocksize)
4436                         return 0;
4437         } else {
4438                 if (inode->i_size >= sizeof(inode->i_block))
4439                         return 0;
4440
4441                 len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
4442                 if (len == sizeof(inode->i_block))
4443                         return 0;
4444         }
4445         if (len != inode->i_size)
4446                 return 0;
4447         return 1;
4448 }
4449
4450 /*
4451  * If the immutable (or append-only) flag is set on the inode, offer
4452  * to clear it.
4453  */
4454 #define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
4455 static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
4456 {
4457         if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
4458                 return;
4459
4460         if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
4461                 return;
4462
4463         pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
4464         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
4465 }
4466
4467 /*
4468  * If device, fifo or socket, check size is zero -- if not offer to
4469  * clear it
4470  */
4471 static void check_size(e2fsck_t ctx, struct problem_context *pctx)
4472 {
4473         struct ext2_inode *inode = pctx->inode;
4474
4475         if ((inode->i_size == 0) && (inode->i_size_high == 0))
4476                 return;
4477
4478         if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
4479                 return;
4480
4481         inode->i_size = 0;
4482         inode->i_size_high = 0;
4483         e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
4484 }
4485
4486 static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
4487 {
4488         struct ext2_super_block *sb = ctx->fs->super;
4489         struct ext2_inode_large *inode;
4490         struct ext2_ext_attr_entry *entry;
4491         char *start, *end;
4492         int storage_size, remain, offs;
4493         int problem = 0;
4494
4495         inode = (struct ext2_inode_large *) pctx->inode;
4496         storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
4497                 inode->i_extra_isize;
4498         start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
4499                 inode->i_extra_isize + sizeof(__u32);
4500         end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
4501         entry = (struct ext2_ext_attr_entry *) start;
4502
4503         /* scan all entry's headers first */
4504
4505         /* take finish entry 0UL into account */
4506         remain = storage_size - sizeof(__u32);
4507         offs = end - start;
4508
4509         while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
4510
4511                 /* header eats this space */
4512                 remain -= sizeof(struct ext2_ext_attr_entry);
4513
4514                 /* is attribute name valid? */
4515                 if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
4516                         pctx->num = entry->e_name_len;
4517                         problem = PR_1_ATTR_NAME_LEN;
4518                         goto fix;
4519                 }
4520
4521                 /* attribute len eats this space */
4522                 remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
4523
4524                 /* check value size */
4525                 if (entry->e_value_size == 0 || entry->e_value_size > remain) {
4526                         pctx->num = entry->e_value_size;
4527                         problem = PR_1_ATTR_VALUE_SIZE;
4528                         goto fix;
4529                 }
4530
4531                 /* check value placement */
4532                 if (entry->e_value_offs +
4533                     EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
4534                         printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
4535                         pctx->num = entry->e_value_offs;
4536                         problem = PR_1_ATTR_VALUE_OFFSET;
4537                         goto fix;
4538                 }
4539
4540                 /* e_value_block must be 0 in inode's ea */
4541                 if (entry->e_value_block != 0) {
4542                         pctx->num = entry->e_value_block;
4543                         problem = PR_1_ATTR_VALUE_BLOCK;
4544                         goto fix;
4545                 }
4546
4547                 /* e_hash must be 0 in inode's ea */
4548                 if (entry->e_hash != 0) {
4549                         pctx->num = entry->e_hash;
4550                         problem = PR_1_ATTR_HASH;
4551                         goto fix;
4552                 }
4553
4554                 remain -= entry->e_value_size;
4555                 offs -= EXT2_XATTR_SIZE(entry->e_value_size);
4556
4557                 entry = EXT2_EXT_ATTR_NEXT(entry);
4558         }
4559 fix:
4560         /*
4561          * it seems like a corruption. it's very unlikely we could repair
4562          * EA(s) in automatic fashion -bzzz
4563          */
4564 #if 0
4565         problem = PR_1_ATTR_HASH;
4566 #endif
4567         if (problem == 0 || !fix_problem(ctx, problem, pctx))
4568                 return;
4569
4570         /* simple remove all possible EA(s) */
4571         *((__u32 *)start) = 0UL;
4572         e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
4573                                 EXT2_INODE_SIZE(sb), "pass1");
4574 }
4575
4576 static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
4577 {
4578         struct ext2_super_block *sb = ctx->fs->super;
4579         struct ext2_inode_large *inode;
4580         __u32 *eamagic;
4581         int min, max;
4582
4583         inode = (struct ext2_inode_large *) pctx->inode;
4584         if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
4585                 /* this isn't large inode. so, nothing to check */
4586                 return;
4587         }
4588
4589 #if 0
4590         printf("inode #%u, i_extra_size %d\n", pctx->ino,
4591                         inode->i_extra_isize);
4592 #endif
4593         /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
4594         min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
4595         max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
4596         /*
4597          * For now we will allow i_extra_isize to be 0, but really
4598          * implementations should never allow i_extra_isize to be 0
4599          */
4600         if (inode->i_extra_isize &&
4601             (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
4602                 if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
4603                         return;
4604                 inode->i_extra_isize = min;
4605                 e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
4606                                         EXT2_INODE_SIZE(sb), "pass1");
4607                 return;
4608         }
4609
4610         eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
4611                         inode->i_extra_isize);
4612         if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
4613                 /* it seems inode has an extended attribute(s) in body */
4614                 check_ea_in_inode(ctx, pctx);
4615         }
4616 }
4617
4618 static void e2fsck_pass1(e2fsck_t ctx)
4619 {
4620         int     i;
4621         __u64   max_sizes;
4622         ext2_filsys fs = ctx->fs;
4623         ext2_ino_t      ino;
4624         struct ext2_inode *inode;
4625         ext2_inode_scan scan;
4626         char            *block_buf;
4627 #ifdef RESOURCE_TRACK
4628         struct resource_track   rtrack;
4629 #endif
4630         unsigned char   frag, fsize;
4631         struct          problem_context pctx;
4632         struct          scan_callback_struct scan_struct;
4633         struct ext2_super_block *sb = ctx->fs->super;
4634         int             imagic_fs;
4635         int             busted_fs_time = 0;
4636         int             inode_size;
4637
4638 #ifdef RESOURCE_TRACK
4639         init_resource_track(&rtrack);
4640 #endif
4641         clear_problem_context(&pctx);
4642
4643         if (!(ctx->options & E2F_OPT_PREEN))
4644                 fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
4645
4646         if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4647             !(ctx->options & E2F_OPT_NO)) {
4648                 if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
4649                         ctx->dirs_to_hash = 0;
4650         }
4651
4652 #ifdef MTRACE
4653         mtrace_print("Pass 1");
4654 #endif
4655
4656 #define EXT2_BPP(bits) (1ULL << ((bits) - 2))
4657
4658         for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
4659                 max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
4660                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
4661                 max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
4662                 max_sizes = (max_sizes * (1UL << i)) - 1;
4663                 ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
4664         }
4665 #undef EXT2_BPP
4666
4667         imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
4668
4669         /*
4670          * Allocate bitmaps structures
4671          */
4672         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
4673                                               &ctx->inode_used_map);
4674         if (pctx.errcode) {
4675                 pctx.num = 1;
4676                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4677                 ctx->flags |= E2F_FLAG_ABORT;
4678                 return;
4679         }
4680         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4681                                 _("directory inode map"), &ctx->inode_dir_map);
4682         if (pctx.errcode) {
4683                 pctx.num = 2;
4684                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4685                 ctx->flags |= E2F_FLAG_ABORT;
4686                 return;
4687         }
4688         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4689                         _("regular file inode map"), &ctx->inode_reg_map);
4690         if (pctx.errcode) {
4691                 pctx.num = 6;
4692                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
4693                 ctx->flags |= E2F_FLAG_ABORT;
4694                 return;
4695         }
4696         pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
4697                                               &ctx->block_found_map);
4698         if (pctx.errcode) {
4699                 pctx.num = 1;
4700                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
4701                 ctx->flags |= E2F_FLAG_ABORT;
4702                 return;
4703         }
4704         pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
4705                                              &ctx->inode_link_info);
4706         if (pctx.errcode) {
4707                 fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
4708                 ctx->flags |= E2F_FLAG_ABORT;
4709                 return;
4710         }
4711         inode_size = EXT2_INODE_SIZE(fs->super);
4712         inode = (struct ext2_inode *)
4713                 e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
4714
4715         inodes_to_process = (struct process_inode_block *)
4716                 e2fsck_allocate_memory(ctx,
4717                                        (ctx->process_inode_size *
4718                                         sizeof(struct process_inode_block)),
4719                                        "array of inodes to process");
4720         process_inode_count = 0;
4721
4722         pctx.errcode = ext2fs_init_dblist(fs, 0);
4723         if (pctx.errcode) {
4724                 fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
4725                 ctx->flags |= E2F_FLAG_ABORT;
4726                 return;
4727         }
4728
4729         /*
4730          * If the last orphan field is set, clear it, since the pass1
4731          * processing will automatically find and clear the orphans.
4732          * In the future, we may want to try using the last_orphan
4733          * linked list ourselves, but for now, we clear it so that the
4734          * ext3 mount code won't get confused.
4735          */
4736         if (!(ctx->options & E2F_OPT_READONLY)) {
4737                 if (fs->super->s_last_orphan) {
4738                         fs->super->s_last_orphan = 0;
4739                         ext2fs_mark_super_dirty(fs);
4740                 }
4741         }
4742
4743         mark_table_blocks(ctx);
4744         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
4745                                                     "block interate buffer");
4746         e2fsck_use_inode_shortcuts(ctx, 1);
4747         ehandler_operation(_("doing inode scan"));
4748         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4749                                               &scan);
4750         if (pctx.errcode) {
4751                 fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
4752                 ctx->flags |= E2F_FLAG_ABORT;
4753                 return;
4754         }
4755         ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
4756         ctx->stashed_inode = inode;
4757         scan_struct.ctx = ctx;
4758         scan_struct.block_buf = block_buf;
4759         ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
4760         if (ctx->progress)
4761                 if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
4762                         return;
4763         if (fs->super->s_wtime < fs->super->s_inodes_count)
4764                 busted_fs_time = 1;
4765
4766         while (1) {
4767                 pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
4768                                                           inode, inode_size);
4769                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4770                         return;
4771                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
4772                         if (!ctx->inode_bb_map)
4773                                 alloc_bb_map(ctx);
4774                         ext2fs_mark_inode_bitmap(ctx->inode_bb_map, ino);
4775                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4776                         continue;
4777                 }
4778                 if (pctx.errcode) {
4779                         fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
4780                         ctx->flags |= E2F_FLAG_ABORT;
4781                         return;
4782                 }
4783                 if (!ino)
4784                         break;
4785                 pctx.ino = ino;
4786                 pctx.inode = inode;
4787                 ctx->stashed_ino = ino;
4788                 if (inode->i_links_count) {
4789                         pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
4790                                            ino, inode->i_links_count);
4791                         if (pctx.errcode) {
4792                                 pctx.num = inode->i_links_count;
4793                                 fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
4794                                 ctx->flags |= E2F_FLAG_ABORT;
4795                                 return;
4796                         }
4797                 }
4798                 if (ino == EXT2_BAD_INO) {
4799                         struct process_block_struct_1 pb;
4800
4801                         pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
4802                                                           &pb.fs_meta_blocks);
4803                         if (pctx.errcode) {
4804                                 pctx.num = 4;
4805                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
4806                                 ctx->flags |= E2F_FLAG_ABORT;
4807                                 return;
4808                         }
4809                         pb.ino = EXT2_BAD_INO;
4810                         pb.num_blocks = pb.last_block = 0;
4811                         pb.num_illegal_blocks = 0;
4812                         pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
4813                         pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
4814                         pb.inode = inode;
4815                         pb.pctx = &pctx;
4816                         pb.ctx = ctx;
4817                         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
4818                                      block_buf, process_bad_block, &pb);
4819                         ext2fs_free_block_bitmap(pb.fs_meta_blocks);
4820                         if (pctx.errcode) {
4821                                 fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
4822                                 ctx->flags |= E2F_FLAG_ABORT;
4823                                 return;
4824                         }
4825                         if (pb.bbcheck)
4826                                 if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
4827                                 ctx->flags |= E2F_FLAG_ABORT;
4828                                 return;
4829                         }
4830                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4831                         clear_problem_context(&pctx);
4832                         continue;
4833                 } else if (ino == EXT2_ROOT_INO) {
4834                         /*
4835                          * Make sure the root inode is a directory; if
4836                          * not, offer to clear it.  It will be
4837                          * regnerated in pass #3.
4838                          */
4839                         if (!LINUX_S_ISDIR(inode->i_mode)) {
4840                                 if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
4841                                         inode->i_dtime = time(0);
4842                                         inode->i_links_count = 0;
4843                                         ext2fs_icount_store(ctx->inode_link_info,
4844                                                             ino, 0);
4845                                         e2fsck_write_inode(ctx, ino, inode,
4846                                                            "pass1");
4847                                 }
4848
4849                         }
4850                         /*
4851                          * If dtime is set, offer to clear it.  mke2fs
4852                          * version 0.2b created filesystems with the
4853                          * dtime field set for the root and lost+found
4854                          * directories.  We won't worry about
4855                          * /lost+found, since that can be regenerated
4856                          * easily.  But we will fix the root directory
4857                          * as a special case.
4858                          */
4859                         if (inode->i_dtime && inode->i_links_count) {
4860                                 if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
4861                                         inode->i_dtime = 0;
4862                                         e2fsck_write_inode(ctx, ino, inode,
4863                                                            "pass1");
4864                                 }
4865                         }
4866                 } else if (ino == EXT2_JOURNAL_INO) {
4867                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4868                         if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
4869                                 if (!LINUX_S_ISREG(inode->i_mode) &&
4870                                     fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
4871                                                 &pctx)) {
4872                                         inode->i_mode = LINUX_S_IFREG;
4873                                         e2fsck_write_inode(ctx, ino, inode,
4874                                                            "pass1");
4875                                 }
4876                                 check_blocks(ctx, &pctx, block_buf);
4877                                 continue;
4878                         }
4879                         if ((inode->i_links_count || inode->i_blocks ||
4880                              inode->i_blocks || inode->i_block[0]) &&
4881                             fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
4882                                         &pctx)) {
4883                                 memset(inode, 0, inode_size);
4884                                 ext2fs_icount_store(ctx->inode_link_info,
4885                                                     ino, 0);
4886                                 e2fsck_write_inode_full(ctx, ino, inode,
4887                                                         inode_size, "pass1");
4888                         }
4889                 } else if (ino < EXT2_FIRST_INODE(fs->super)) {
4890                         int     problem = 0;
4891
4892                         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4893                         if (ino == EXT2_BOOT_LOADER_INO) {
4894                                 if (LINUX_S_ISDIR(inode->i_mode))
4895                                         problem = PR_1_RESERVED_BAD_MODE;
4896                         } else if (ino == EXT2_RESIZE_INO) {
4897                                 if (inode->i_mode &&
4898                                     !LINUX_S_ISREG(inode->i_mode))
4899                                         problem = PR_1_RESERVED_BAD_MODE;
4900                         } else {
4901                                 if (inode->i_mode != 0)
4902                                         problem = PR_1_RESERVED_BAD_MODE;
4903                         }
4904                         if (problem) {
4905                                 if (fix_problem(ctx, problem, &pctx)) {
4906                                         inode->i_mode = 0;
4907                                         e2fsck_write_inode(ctx, ino, inode,
4908                                                            "pass1");
4909                                 }
4910                         }
4911                         check_blocks(ctx, &pctx, block_buf);
4912                         continue;
4913                 }
4914                 /*
4915                  * Check for inodes who might have been part of the
4916                  * orphaned list linked list.  They should have gotten
4917                  * dealt with by now, unless the list had somehow been
4918                  * corrupted.
4919                  *
4920                  * FIXME: In the future, inodes which are still in use
4921                  * (and which are therefore) pending truncation should
4922                  * be handled specially.  Right now we just clear the
4923                  * dtime field, and the normal e2fsck handling of
4924                  * inodes where i_size and the inode blocks are
4925                  * inconsistent is to fix i_size, instead of releasing
4926                  * the extra blocks.  This won't catch the inodes that
4927                  * was at the end of the orphan list, but it's better
4928                  * than nothing.  The right answer is that there
4929                  * shouldn't be any bugs in the orphan list handling.  :-)
4930                  */
4931                 if (inode->i_dtime && !busted_fs_time &&
4932                     inode->i_dtime < ctx->fs->super->s_inodes_count) {
4933                         if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
4934                                 inode->i_dtime = inode->i_links_count ?
4935                                         0 : time(0);
4936                                 e2fsck_write_inode(ctx, ino, inode,
4937                                                    "pass1");
4938                         }
4939                 }
4940
4941                 /*
4942                  * This code assumes that deleted inodes have
4943                  * i_links_count set to 0.
4944                  */
4945                 if (!inode->i_links_count) {
4946                         if (!inode->i_dtime && inode->i_mode) {
4947                                 if (fix_problem(ctx,
4948                                             PR_1_ZERO_DTIME, &pctx)) {
4949                                         inode->i_dtime = time(0);
4950                                         e2fsck_write_inode(ctx, ino, inode,
4951                                                            "pass1");
4952                                 }
4953                         }
4954                         continue;
4955                 }
4956                 /*
4957                  * n.b.  0.3c ext2fs code didn't clear i_links_count for
4958                  * deleted files.  Oops.
4959                  *
4960                  * Since all new ext2 implementations get this right,
4961                  * we now assume that the case of non-zero
4962                  * i_links_count and non-zero dtime means that we
4963                  * should keep the file, not delete it.
4964                  *
4965                  */
4966                 if (inode->i_dtime) {
4967                         if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
4968                                 inode->i_dtime = 0;
4969                                 e2fsck_write_inode(ctx, ino, inode, "pass1");
4970                         }
4971                 }
4972
4973                 ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
4974                 switch (fs->super->s_creator_os) {
4975                     case EXT2_OS_LINUX:
4976                         frag = inode->osd2.linux2.l_i_frag;
4977                         fsize = inode->osd2.linux2.l_i_fsize;
4978                         break;
4979                     case EXT2_OS_HURD:
4980                         frag = inode->osd2.hurd2.h_i_frag;
4981                         fsize = inode->osd2.hurd2.h_i_fsize;
4982                         break;
4983                     case EXT2_OS_MASIX:
4984                         frag = inode->osd2.masix2.m_i_frag;
4985                         fsize = inode->osd2.masix2.m_i_fsize;
4986                         break;
4987                     default:
4988                         frag = fsize = 0;
4989                 }
4990
4991                 if (inode->i_faddr || frag || fsize ||
4992                     (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
4993                         mark_inode_bad(ctx, ino);
4994                 if (inode->i_flags & EXT2_IMAGIC_FL) {
4995                         if (imagic_fs) {
4996                                 if (!ctx->inode_imagic_map)
4997                                         alloc_imagic_map(ctx);
4998                                 ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
4999                                                          ino);
5000                         } else {
5001                                 if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
5002                                         inode->i_flags &= ~EXT2_IMAGIC_FL;
5003                                         e2fsck_write_inode(ctx, ino,
5004                                                            inode, "pass1");
5005                                 }
5006                         }
5007                 }
5008
5009                 check_inode_extra_space(ctx, &pctx);
5010
5011                 if (LINUX_S_ISDIR(inode->i_mode)) {
5012                         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
5013                         e2fsck_add_dir_info(ctx, ino, 0);
5014                         ctx->fs_directory_count++;
5015                 } else if (LINUX_S_ISREG (inode->i_mode)) {
5016                         ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
5017                         ctx->fs_regular_count++;
5018                 } else if (LINUX_S_ISCHR (inode->i_mode) &&
5019                            e2fsck_pass1_check_device_inode(fs, inode)) {
5020                         check_immutable(ctx, &pctx);
5021                         check_size(ctx, &pctx);
5022                         ctx->fs_chardev_count++;
5023                 } else if (LINUX_S_ISBLK (inode->i_mode) &&
5024                            e2fsck_pass1_check_device_inode(fs, inode)) {
5025                         check_immutable(ctx, &pctx);
5026                         check_size(ctx, &pctx);
5027                         ctx->fs_blockdev_count++;
5028                 } else if (LINUX_S_ISLNK (inode->i_mode) &&
5029                            e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
5030                         check_immutable(ctx, &pctx);
5031                         ctx->fs_symlinks_count++;
5032                         if (ext2fs_inode_data_blocks(fs, inode) == 0) {
5033                                 ctx->fs_fast_symlinks_count++;
5034                                 check_blocks(ctx, &pctx, block_buf);
5035                                 continue;
5036                         }
5037                 }
5038                 else if (LINUX_S_ISFIFO (inode->i_mode) &&
5039                          e2fsck_pass1_check_device_inode(fs, inode)) {
5040                         check_immutable(ctx, &pctx);
5041                         check_size(ctx, &pctx);
5042                         ctx->fs_fifo_count++;
5043                 } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
5044                            e2fsck_pass1_check_device_inode(fs, inode)) {
5045                         check_immutable(ctx, &pctx);
5046                         check_size(ctx, &pctx);
5047                         ctx->fs_sockets_count++;
5048                 } else
5049                         mark_inode_bad(ctx, ino);
5050                 if (inode->i_block[EXT2_IND_BLOCK])
5051                         ctx->fs_ind_count++;
5052                 if (inode->i_block[EXT2_DIND_BLOCK])
5053                         ctx->fs_dind_count++;
5054                 if (inode->i_block[EXT2_TIND_BLOCK])
5055                         ctx->fs_tind_count++;
5056                 if (inode->i_block[EXT2_IND_BLOCK] ||
5057                     inode->i_block[EXT2_DIND_BLOCK] ||
5058                     inode->i_block[EXT2_TIND_BLOCK] ||
5059                     inode->i_file_acl) {
5060                         inodes_to_process[process_inode_count].ino = ino;
5061                         inodes_to_process[process_inode_count].inode = *inode;
5062                         process_inode_count++;
5063                 } else
5064                         check_blocks(ctx, &pctx, block_buf);
5065
5066                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5067                         return;
5068
5069                 if (process_inode_count >= ctx->process_inode_size) {
5070                         process_inodes(ctx, block_buf);
5071
5072                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5073                                 return;
5074                 }
5075         }
5076         process_inodes(ctx, block_buf);
5077         ext2fs_close_inode_scan(scan);
5078         ehandler_operation(0);
5079
5080         /*
5081          * If any extended attribute blocks' reference counts need to
5082          * be adjusted, either up (ctx->refcount_extra), or down
5083          * (ctx->refcount), then fix them.
5084          */
5085         if (ctx->refcount) {
5086                 adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
5087                 ea_refcount_free(ctx->refcount);
5088                 ctx->refcount = 0;
5089         }
5090         if (ctx->refcount_extra) {
5091                 adjust_extattr_refcount(ctx, ctx->refcount_extra,
5092                                         block_buf, +1);
5093                 ea_refcount_free(ctx->refcount_extra);
5094                 ctx->refcount_extra = 0;
5095         }
5096
5097         if (ctx->invalid_bitmaps)
5098                 handle_fs_bad_blocks(ctx);
5099
5100         /* We don't need the block_ea_map any more */
5101         if (ctx->block_ea_map) {
5102                 ext2fs_free_block_bitmap(ctx->block_ea_map);
5103                 ctx->block_ea_map = 0;
5104         }
5105
5106         if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
5107                 ext2fs_block_bitmap save_bmap;
5108
5109                 save_bmap = fs->block_map;
5110                 fs->block_map = ctx->block_found_map;
5111                 clear_problem_context(&pctx);
5112                 pctx.errcode = ext2fs_create_resize_inode(fs);
5113                 if (pctx.errcode) {
5114                         fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
5115                         /* Should never get here */
5116                         ctx->flags |= E2F_FLAG_ABORT;
5117                         return;
5118                 }
5119                 fs->block_map = save_bmap;
5120                 ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
5121         }
5122
5123         if (ctx->flags & E2F_FLAG_RESTART) {
5124                 /*
5125                  * Only the master copy of the superblock and block
5126                  * group descriptors are going to be written during a
5127                  * restart, so set the superblock to be used to be the
5128                  * master superblock.
5129                  */
5130                 ctx->use_superblock = 0;
5131                 unwind_pass1();
5132                 goto endit;
5133         }
5134
5135         if (ctx->block_dup_map) {
5136                 if (ctx->options & E2F_OPT_PREEN) {
5137                         clear_problem_context(&pctx);
5138                         fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
5139                 }
5140                 e2fsck_pass1_dupblocks(ctx, block_buf);
5141         }
5142         ext2fs_free_mem(&inodes_to_process);
5143 endit:
5144         e2fsck_use_inode_shortcuts(ctx, 0);
5145
5146         ext2fs_free_mem(&block_buf);
5147         ext2fs_free_mem(&inode);
5148
5149 #ifdef RESOURCE_TRACK
5150         if (ctx->options & E2F_OPT_TIME2) {
5151                 e2fsck_clear_progbar(ctx);
5152                 print_resource_track(_("Pass 1"), &rtrack);
5153         }
5154 #endif
5155 }
5156
5157 /*
5158  * When the inode_scan routines call this callback at the end of the
5159  * glock group, call process_inodes.
5160  */
5161 static errcode_t scan_callback(ext2_filsys fs,
5162                                ext2_inode_scan scan FSCK_ATTR((unused)),
5163                                dgrp_t group, void * priv_data)
5164 {
5165         struct scan_callback_struct *scan_struct;
5166         e2fsck_t ctx;
5167
5168         scan_struct = (struct scan_callback_struct *) priv_data;
5169         ctx = scan_struct->ctx;
5170
5171         process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
5172
5173         if (ctx->progress)
5174                 if ((ctx->progress)(ctx, 1, group+1,
5175                                     ctx->fs->group_desc_count))
5176                         return EXT2_ET_CANCEL_REQUESTED;
5177
5178         return 0;
5179 }
5180
5181 /*
5182  * Process the inodes in the "inodes to process" list.
5183  */
5184 static void process_inodes(e2fsck_t ctx, char *block_buf)
5185 {
5186         int                     i;
5187         struct ext2_inode       *old_stashed_inode;
5188         ext2_ino_t              old_stashed_ino;
5189         const char              *old_operation;
5190         char                    buf[80];
5191         struct problem_context  pctx;
5192
5193 #if 0
5194         printf("begin process_inodes: ");
5195 #endif
5196         if (process_inode_count == 0)
5197                 return;
5198         old_operation = ehandler_operation(0);
5199         old_stashed_inode = ctx->stashed_inode;
5200         old_stashed_ino = ctx->stashed_ino;
5201         qsort(inodes_to_process, process_inode_count,
5202                       sizeof(struct process_inode_block), process_inode_cmp);
5203         clear_problem_context(&pctx);
5204         for (i=0; i < process_inode_count; i++) {
5205                 pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
5206                 pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
5207
5208 #if 0
5209                 printf("%u ", pctx.ino);
5210 #endif
5211                 sprintf(buf, _("reading indirect blocks of inode %u"),
5212                         pctx.ino);
5213                 ehandler_operation(buf);
5214                 check_blocks(ctx, &pctx, block_buf);
5215                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5216                         break;
5217         }
5218         ctx->stashed_inode = old_stashed_inode;
5219         ctx->stashed_ino = old_stashed_ino;
5220         process_inode_count = 0;
5221 #if 0
5222         printf("end process inodes\n");
5223 #endif
5224         ehandler_operation(old_operation);
5225 }
5226
5227 static EXT2_QSORT_TYPE process_inode_cmp(const void *a, const void *b)
5228 {
5229         const struct process_inode_block *ib_a =
5230                 (const struct process_inode_block *) a;
5231         const struct process_inode_block *ib_b =
5232                 (const struct process_inode_block *) b;
5233         int     ret;
5234
5235         ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
5236                ib_b->inode.i_block[EXT2_IND_BLOCK]);
5237         if (ret == 0)
5238                 ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
5239         return ret;
5240 }
5241
5242 /*
5243  * Mark an inode as being bad in some what
5244  */
5245 static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
5246 {
5247         struct          problem_context pctx;
5248
5249         if (!ctx->inode_bad_map) {
5250                 clear_problem_context(&pctx);
5251
5252                 pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
5253                             _("bad inode map"), &ctx->inode_bad_map);
5254                 if (pctx.errcode) {
5255                         pctx.num = 3;
5256                         fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
5257                         /* Should never get here */
5258                         ctx->flags |= E2F_FLAG_ABORT;
5259                         return;
5260                 }
5261         }
5262         ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
5263 }
5264
5265
5266 /*
5267  * This procedure will allocate the inode "bb" (badblock) map table
5268  */
5269 static void alloc_bb_map(e2fsck_t ctx)
5270 {
5271         struct          problem_context pctx;
5272
5273         clear_problem_context(&pctx);
5274         pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
5275                                               _("inode in bad block map"),
5276                                               &ctx->inode_bb_map);
5277         if (pctx.errcode) {
5278                 pctx.num = 4;
5279                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
5280                 /* Should never get here */
5281                 ctx->flags |= E2F_FLAG_ABORT;
5282                 return;
5283         }
5284 }
5285
5286 /*
5287  * This procedure will allocate the inode imagic table
5288  */
5289 static void alloc_imagic_map(e2fsck_t ctx)
5290 {
5291         struct          problem_context pctx;
5292
5293         clear_problem_context(&pctx);
5294         pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
5295                                               _("imagic inode map"),
5296                                               &ctx->inode_imagic_map);
5297         if (pctx.errcode) {
5298                 pctx.num = 5;
5299                 fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
5300                 /* Should never get here */
5301                 ctx->flags |= E2F_FLAG_ABORT;
5302                 return;
5303         }
5304 }
5305
5306 /*
5307  * Marks a block as in use, setting the dup_map if it's been set
5308  * already.  Called by process_block and process_bad_block.
5309  *
5310  * WARNING: Assumes checks have already been done to make sure block
5311  * is valid.  This is true in both process_block and process_bad_block.
5312  */
5313 static _INLINE_ void mark_block_used(e2fsck_t ctx, blk_t block)
5314 {
5315         struct          problem_context pctx;
5316
5317         clear_problem_context(&pctx);
5318
5319         if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
5320                 if (!ctx->block_dup_map) {
5321                         pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
5322                               _("multiply claimed block map"),
5323                               &ctx->block_dup_map);
5324                         if (pctx.errcode) {
5325                                 pctx.num = 3;
5326                                 fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
5327                                             &pctx);
5328                                 /* Should never get here */
5329                                 ctx->flags |= E2F_FLAG_ABORT;
5330                                 return;
5331                         }
5332                 }
5333                 ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
5334         } else {
5335                 ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
5336         }
5337 }
5338
5339 /*
5340  * Adjust the extended attribute block's reference counts at the end
5341  * of pass 1, either by subtracting out references for EA blocks that
5342  * are still referenced in ctx->refcount, or by adding references for
5343  * EA blocks that had extra references as accounted for in
5344  * ctx->refcount_extra.
5345  */
5346 static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
5347                                     char *block_buf, int adjust_sign)
5348 {
5349         struct ext2_ext_attr_header     *header;
5350         struct problem_context          pctx;
5351         ext2_filsys                     fs = ctx->fs;
5352         blk_t                           blk;
5353         __u32                           should_be;
5354         int                             count;
5355
5356         clear_problem_context(&pctx);
5357
5358         ea_refcount_intr_begin(refcount);
5359         while (1) {
5360                 if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
5361                         break;
5362                 pctx.blk = blk;
5363                 pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
5364                 if (pctx.errcode) {
5365                         fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
5366                         return;
5367                 }
5368                 header = (struct ext2_ext_attr_header *) block_buf;
5369                 pctx.blkcount = header->h_refcount;
5370                 should_be = header->h_refcount + adjust_sign * count;
5371                 pctx.num = should_be;
5372                 if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
5373                         header->h_refcount = should_be;
5374                         pctx.errcode = ext2fs_write_ext_attr(fs, blk,
5375                                                              block_buf);
5376                         if (pctx.errcode) {
5377                                 fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
5378                                 continue;
5379                         }
5380                 }
5381         }
5382 }
5383
5384 /*
5385  * Handle processing the extended attribute blocks
5386  */
5387 static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
5388                            char *block_buf)
5389 {
5390         ext2_filsys fs = ctx->fs;
5391         ext2_ino_t      ino = pctx->ino;
5392         struct ext2_inode *inode = pctx->inode;
5393         blk_t           blk;
5394         char *          end;
5395         struct ext2_ext_attr_header *header;
5396         struct ext2_ext_attr_entry *entry;
5397         int             count;
5398         region_t        region;
5399
5400         blk = inode->i_file_acl;
5401         if (blk == 0)
5402                 return 0;
5403
5404         /*
5405          * If the Extended attribute flag isn't set, then a non-zero
5406          * file acl means that the inode is corrupted.
5407          *
5408          * Or if the extended attribute block is an invalid block,
5409          * then the inode is also corrupted.
5410          */
5411         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
5412             (blk < fs->super->s_first_data_block) ||
5413             (blk >= fs->super->s_blocks_count)) {
5414                 mark_inode_bad(ctx, ino);
5415                 return 0;
5416         }
5417
5418         /* If ea bitmap hasn't been allocated, create it */
5419         if (!ctx->block_ea_map) {
5420                 pctx->errcode = ext2fs_allocate_block_bitmap(fs,
5421                                                       _("ext attr block map"),
5422                                                       &ctx->block_ea_map);
5423                 if (pctx->errcode) {
5424                         pctx->num = 2;
5425                         fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
5426                         ctx->flags |= E2F_FLAG_ABORT;
5427                         return 0;
5428                 }
5429         }
5430
5431         /* Create the EA refcount structure if necessary */
5432         if (!ctx->refcount) {
5433                 pctx->errcode = ea_refcount_create(0, &ctx->refcount);
5434                 if (pctx->errcode) {
5435                         pctx->num = 1;
5436                         fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
5437                         ctx->flags |= E2F_FLAG_ABORT;
5438                         return 0;
5439                 }
5440         }
5441
5442 #if 0
5443         /* Debugging text */
5444         printf("Inode %u has EA block %u\n", ino, blk);
5445 #endif
5446
5447         /* Have we seen this EA block before? */
5448         if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
5449                 if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
5450                         return 1;
5451                 /* Ooops, this EA was referenced more than it stated */
5452                 if (!ctx->refcount_extra) {
5453                         pctx->errcode = ea_refcount_create(0,
5454                                            &ctx->refcount_extra);
5455                         if (pctx->errcode) {
5456                                 pctx->num = 2;
5457                                 fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
5458                                 ctx->flags |= E2F_FLAG_ABORT;
5459                                 return 0;
5460                         }
5461                 }
5462                 ea_refcount_increment(ctx->refcount_extra, blk, 0);
5463                 return 1;
5464         }
5465
5466         /*
5467          * OK, we haven't seen this EA block yet.  So we need to
5468          * validate it
5469          */
5470         pctx->blk = blk;
5471         pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
5472         if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
5473                 goto clear_extattr;
5474         header = (struct ext2_ext_attr_header *) block_buf;
5475         pctx->blk = inode->i_file_acl;
5476         if (((ctx->ext_attr_ver == 1) &&
5477              (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
5478             ((ctx->ext_attr_ver == 2) &&
5479              (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
5480                 if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
5481                         goto clear_extattr;
5482         }
5483
5484         if (header->h_blocks != 1) {
5485                 if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
5486                         goto clear_extattr;
5487         }
5488
5489         region = region_create(0, fs->blocksize);
5490         if (!region) {
5491                 fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
5492                 ctx->flags |= E2F_FLAG_ABORT;
5493                 return 0;
5494         }
5495         if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
5496                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5497                         goto clear_extattr;
5498         }
5499
5500         entry = (struct ext2_ext_attr_entry *)(header+1);
5501         end = block_buf + fs->blocksize;
5502         while ((char *)entry < end && *(__u32 *)entry) {
5503                 if (region_allocate(region, (char *)entry - (char *)header,
5504                                    EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
5505                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5506                                 goto clear_extattr;
5507                 }
5508                 if ((ctx->ext_attr_ver == 1 &&
5509                      (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
5510                     (ctx->ext_attr_ver == 2 &&
5511                      entry->e_name_index == 0)) {
5512                         if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
5513                                 goto clear_extattr;
5514                 }
5515                 if (entry->e_value_block != 0) {
5516                         if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
5517                                 goto clear_extattr;
5518                 }
5519                 if (entry->e_value_size &&
5520                     region_allocate(region, entry->e_value_offs,
5521                                     EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
5522                         if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5523                                 goto clear_extattr;
5524                 }
5525                 entry = EXT2_EXT_ATTR_NEXT(entry);
5526         }
5527         if (region_allocate(region, (char *)entry - (char *)header, 4)) {
5528                 if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
5529                         goto clear_extattr;
5530         }
5531         region_free(region);
5532
5533         count = header->h_refcount - 1;
5534         if (count)
5535                 ea_refcount_store(ctx->refcount, blk, count);
5536         mark_block_used(ctx, blk);
5537         ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
5538
5539         return 1;
5540
5541 clear_extattr:
5542         inode->i_file_acl = 0;
5543         e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
5544         return 0;
5545 }
5546
5547 /* Returns 1 if bad htree, 0 if OK */
5548 static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
5549                         ext2_ino_t ino FSCK_ATTR((unused)),
5550                         struct ext2_inode *inode,
5551                         char *block_buf)
5552 {
5553         struct ext2_dx_root_info        *root;
5554         ext2_filsys                     fs = ctx->fs;
5555         errcode_t                       retval;
5556         blk_t                           blk;
5557
5558         if ((!LINUX_S_ISDIR(inode->i_mode) &&
5559              fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
5560             (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
5561              fix_problem(ctx, PR_1_HTREE_SET, pctx)))
5562                 return 1;
5563
5564         blk = inode->i_block[0];
5565         if (((blk == 0) ||
5566              (blk < fs->super->s_first_data_block) ||
5567              (blk >= fs->super->s_blocks_count)) &&
5568             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5569                 return 1;
5570
5571         retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
5572         if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5573                 return 1;
5574
5575         /* XXX should check that beginning matches a directory */
5576         root = (struct ext2_dx_root_info *) (block_buf + 24);
5577
5578         if ((root->reserved_zero || root->info_length < 8) &&
5579             fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
5580                 return 1;
5581
5582         pctx->num = root->hash_version;
5583         if ((root->hash_version != EXT2_HASH_LEGACY) &&
5584             (root->hash_version != EXT2_HASH_HALF_MD4) &&
5585             (root->hash_version != EXT2_HASH_TEA) &&
5586             fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
5587                 return 1;
5588
5589         if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
5590             fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
5591                 return 1;
5592
5593         pctx->num = root->indirect_levels;
5594         if ((root->indirect_levels > 1) &&
5595             fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
5596                 return 1;
5597
5598         return 0;
5599 }
5600
5601 /*
5602  * This subroutine is called on each inode to account for all of the
5603  * blocks used by that inode.
5604  */
5605 static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
5606                          char *block_buf)
5607 {
5608         ext2_filsys fs = ctx->fs;
5609         struct process_block_struct_1 pb;
5610         ext2_ino_t      ino = pctx->ino;
5611         struct ext2_inode *inode = pctx->inode;
5612         int             bad_size = 0;
5613         int             dirty_inode = 0;
5614         __u64           size;
5615
5616         pb.ino = ino;
5617         pb.num_blocks = 0;
5618         pb.last_block = -1;
5619         pb.num_illegal_blocks = 0;
5620         pb.suppress = 0; pb.clear = 0;
5621         pb.fragmented = 0;
5622         pb.compressed = 0;
5623         pb.previous_block = 0;
5624         pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
5625         pb.is_reg = LINUX_S_ISREG(inode->i_mode);
5626         pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
5627         pb.inode = inode;
5628         pb.pctx = pctx;
5629         pb.ctx = ctx;
5630         pctx->ino = ino;
5631         pctx->errcode = 0;
5632
5633         if (inode->i_flags & EXT2_COMPRBLK_FL) {
5634                 if (fs->super->s_feature_incompat &
5635                     EXT2_FEATURE_INCOMPAT_COMPRESSION)
5636                         pb.compressed = 1;
5637                 else {
5638                         if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
5639                                 inode->i_flags &= ~EXT2_COMPRBLK_FL;
5640                                 dirty_inode++;
5641                         }
5642                 }
5643         }
5644
5645         if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
5646                 pb.num_blocks++;
5647
5648         if (ext2fs_inode_has_valid_blocks(inode))
5649                 pctx->errcode = ext2fs_block_iterate2(fs, ino,
5650                                        pb.is_dir ? BLOCK_FLAG_HOLE : 0,
5651                                        block_buf, process_block, &pb);
5652         end_problem_latch(ctx, PR_LATCH_BLOCK);
5653         end_problem_latch(ctx, PR_LATCH_TOOBIG);
5654         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5655                 goto out;
5656         if (pctx->errcode)
5657                 fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
5658
5659         if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
5660                 ctx->fs_fragmented++;
5661
5662         if (pb.clear) {
5663                 inode->i_links_count = 0;
5664                 ext2fs_icount_store(ctx->inode_link_info, ino, 0);
5665                 inode->i_dtime = time(0);
5666                 dirty_inode++;
5667                 ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5668                 ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
5669                 ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5670                 /*
5671                  * The inode was probably partially accounted for
5672                  * before processing was aborted, so we need to
5673                  * restart the pass 1 scan.
5674                  */
5675                 ctx->flags |= E2F_FLAG_RESTART;
5676                 goto out;
5677         }
5678
5679         if (inode->i_flags & EXT2_INDEX_FL) {
5680                 if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
5681                         inode->i_flags &= ~EXT2_INDEX_FL;
5682                         dirty_inode++;
5683                 } else {
5684 #ifdef ENABLE_HTREE
5685                         e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
5686 #endif
5687                 }
5688         }
5689         if (ctx->dirs_to_hash && pb.is_dir &&
5690             !(inode->i_flags & EXT2_INDEX_FL) &&
5691             ((inode->i_size / fs->blocksize) >= 3))
5692                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
5693
5694         if (!pb.num_blocks && pb.is_dir) {
5695                 if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
5696                         inode->i_links_count = 0;
5697                         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
5698                         inode->i_dtime = time(0);
5699                         dirty_inode++;
5700                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5701                         ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
5702                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5703                         ctx->fs_directory_count--;
5704                         goto out;
5705                 }
5706         }
5707
5708         pb.num_blocks *= (fs->blocksize / 512);
5709 #if 0
5710         printf("inode %u, i_size = %lu, last_block = %lld, i_blocks=%lu, num_blocks = %lu\n",
5711                ino, inode->i_size, pb.last_block, inode->i_blocks,
5712                pb.num_blocks);
5713 #endif
5714         if (pb.is_dir) {
5715                 int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
5716                 if (nblock > (pb.last_block + 1))
5717                         bad_size = 1;
5718                 else if (nblock < (pb.last_block + 1)) {
5719                         if (((pb.last_block + 1) - nblock) >
5720                             fs->super->s_prealloc_dir_blocks)
5721                                 bad_size = 2;
5722                 }
5723         } else {
5724                 size = EXT2_I_SIZE(inode);
5725                 if ((pb.last_block >= 0) &&
5726                     (size < (__u64) pb.last_block * fs->blocksize))
5727                         bad_size = 3;
5728                 else if (size > ext2_max_sizes[fs->super->s_log_block_size])
5729                         bad_size = 4;
5730         }
5731         /* i_size for symlinks is checked elsewhere */
5732         if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
5733                 pctx->num = (pb.last_block+1) * fs->blocksize;
5734                 if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
5735                         inode->i_size = pctx->num;
5736                         if (!LINUX_S_ISDIR(inode->i_mode))
5737                                 inode->i_size_high = pctx->num >> 32;
5738                         dirty_inode++;
5739                 }
5740                 pctx->num = 0;
5741         }
5742         if (LINUX_S_ISREG(inode->i_mode) &&
5743             (inode->i_size_high || inode->i_size & 0x80000000UL))
5744                 ctx->large_files++;
5745         if (pb.num_blocks != inode->i_blocks) {
5746                 pctx->num = pb.num_blocks;
5747                 if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
5748                         inode->i_blocks = pb.num_blocks;
5749                         dirty_inode++;
5750                 }
5751                 pctx->num = 0;
5752         }
5753 out:
5754         if (dirty_inode)
5755                 e2fsck_write_inode(ctx, ino, inode, "check_blocks");
5756 }
5757
5758 #if 0
5759 /*
5760  * Helper function called by process block when an illegal block is
5761  * found.  It returns a description about why the block is illegal
5762  */
5763 static char *describe_illegal_block(ext2_filsys fs, blk_t block)
5764 {
5765         blk_t   super;
5766         int     i;
5767         static char     problem[80];
5768
5769         super = fs->super->s_first_data_block;
5770         strcpy(problem, "PROGRAMMING ERROR: Unknown reason for illegal block");
5771         if (block < super) {
5772                 sprintf(problem, "< FIRSTBLOCK (%u)", super);
5773                 return(problem);
5774         } else if (block >= fs->super->s_blocks_count) {
5775                 sprintf(problem, "> BLOCKS (%u)", fs->super->s_blocks_count);
5776                 return(problem);
5777         }
5778         for (i = 0; i < fs->group_desc_count; i++) {
5779                 if (block == super) {
5780                         sprintf(problem, "is the superblock in group %d", i);
5781                         break;
5782                 }
5783                 if (block > super &&
5784                     block <= (super + fs->desc_blocks)) {
5785                         sprintf(problem, "is in the group descriptors "
5786                                 "of group %d", i);
5787                         break;
5788                 }
5789                 if (block == fs->group_desc[i].bg_block_bitmap) {
5790                         sprintf(problem, "is the block bitmap of group %d", i);
5791                         break;
5792                 }
5793                 if (block == fs->group_desc[i].bg_inode_bitmap) {
5794                         sprintf(problem, "is the inode bitmap of group %d", i);
5795                         break;
5796                 }
5797                 if (block >= fs->group_desc[i].bg_inode_table &&
5798                     (block < fs->group_desc[i].bg_inode_table
5799                      + fs->inode_blocks_per_group)) {
5800                         sprintf(problem, "is in the inode table of group %d",
5801                                 i);
5802                         break;
5803                 }
5804                 super += fs->super->s_blocks_per_group;
5805         }
5806         return(problem);
5807 }
5808 #endif
5809
5810 /*
5811  * This is a helper function for check_blocks().
5812  */
5813 static int process_block(ext2_filsys fs,
5814                   blk_t *block_nr,
5815                   e2_blkcnt_t blockcnt,
5816                   blk_t ref_block FSCK_ATTR((unused)),
5817                   int ref_offset FSCK_ATTR((unused)),
5818                   void *priv_data)
5819 {
5820         struct process_block_struct_1 *p;
5821         struct problem_context *pctx;
5822         blk_t   blk = *block_nr;
5823         int     ret_code = 0;
5824         int     problem = 0;
5825         e2fsck_t        ctx;
5826
5827         p = (struct process_block_struct_1 *) priv_data;
5828         pctx = p->pctx;
5829         ctx = p->ctx;
5830
5831         if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
5832                 /* todo: Check that the comprblk_fl is high, that the
5833                    blkaddr pattern looks right (all non-holes up to
5834                    first EXT2FS_COMPRESSED_BLKADDR, then all
5835                    EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
5836                    that the feature_incompat bit is high, and that the
5837                    inode is a regular file.  If we're doing a "full
5838                    check" (a concept introduced to e2fsck by e2compr,
5839                    meaning that we look at data blocks as well as
5840                    metadata) then call some library routine that
5841                    checks the compressed data.  I'll have to think
5842                    about this, because one particularly important
5843                    problem to be able to fix is to recalculate the
5844                    cluster size if necessary.  I think that perhaps
5845                    we'd better do most/all e2compr-specific checks
5846                    separately, after the non-e2compr checks.  If not
5847                    doing a full check, it may be useful to test that
5848                    the personality is linux; e.g. if it isn't then
5849                    perhaps this really is just an illegal block. */
5850                 return 0;
5851         }
5852
5853         if (blk == 0) {
5854                 if (p->is_dir == 0) {
5855                         /*
5856                          * Should never happen, since only directories
5857                          * get called with BLOCK_FLAG_HOLE
5858                          */
5859 #if DEBUG_E2FSCK
5860                         printf("process_block() called with blk == 0, "
5861                                "blockcnt=%d, inode %lu???\n",
5862                                blockcnt, p->ino);
5863 #endif
5864                         return 0;
5865                 }
5866                 if (blockcnt < 0)
5867                         return 0;
5868                 if (blockcnt * fs->blocksize < p->inode->i_size) {
5869 #if 0
5870                         printf("Missing block (#%d) in directory inode %lu!\n",
5871                                blockcnt, p->ino);
5872 #endif
5873                         goto mark_dir;
5874                 }
5875                 return 0;
5876         }
5877
5878 #if 0
5879         printf("Process_block, inode %lu, block %u, #%d\n", p->ino, blk,
5880                blockcnt);
5881 #endif
5882
5883         /*
5884          * Simplistic fragmentation check.  We merely require that the
5885          * file be contiguous.  (Which can never be true for really
5886          * big files that are greater than a block group.)
5887          */
5888         if (!HOLE_BLKADDR(p->previous_block)) {
5889                 if (p->previous_block+1 != blk)
5890                         p->fragmented = 1;
5891         }
5892         p->previous_block = blk;
5893
5894         if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
5895                 problem = PR_1_TOOBIG_DIR;
5896         if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
5897                 problem = PR_1_TOOBIG_REG;
5898         if (!p->is_dir && !p->is_reg && blockcnt > 0)
5899                 problem = PR_1_TOOBIG_SYMLINK;
5900
5901         if (blk < fs->super->s_first_data_block ||
5902             blk >= fs->super->s_blocks_count)
5903                 problem = PR_1_ILLEGAL_BLOCK_NUM;
5904
5905         if (problem) {
5906                 p->num_illegal_blocks++;
5907                 if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
5908                         if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
5909                                 p->clear = 1;
5910                                 return BLOCK_ABORT;
5911                         }
5912                         if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
5913                                 p->suppress = 1;
5914                                 set_latch_flags(PR_LATCH_BLOCK,
5915                                                 PRL_SUPPRESS, 0);
5916                         }
5917                 }
5918                 pctx->blk = blk;
5919                 pctx->blkcount = blockcnt;
5920                 if (fix_problem(ctx, problem, pctx)) {
5921                         blk = *block_nr = 0;
5922                         ret_code = BLOCK_CHANGED;
5923                         goto mark_dir;
5924                 } else
5925                         return 0;
5926         }
5927
5928         if (p->ino == EXT2_RESIZE_INO) {
5929                 /*
5930                  * The resize inode has already be sanity checked
5931                  * during pass #0 (the superblock checks).  All we
5932                  * have to do is mark the double indirect block as
5933                  * being in use; all of the other blocks are handled
5934                  * by mark_table_blocks()).
5935                  */
5936                 if (blockcnt == BLOCK_COUNT_DIND)
5937                         mark_block_used(ctx, blk);
5938         } else
5939                 mark_block_used(ctx, blk);
5940         p->num_blocks++;
5941         if (blockcnt >= 0)
5942                 p->last_block = blockcnt;
5943 mark_dir:
5944         if (p->is_dir && (blockcnt >= 0)) {
5945                 pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
5946                                                     blk, blockcnt);
5947                 if (pctx->errcode) {
5948                         pctx->blk = blk;
5949                         pctx->num = blockcnt;
5950                         fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
5951                         /* Should never get here */
5952                         ctx->flags |= E2F_FLAG_ABORT;
5953                         return BLOCK_ABORT;
5954                 }
5955         }
5956         return ret_code;
5957 }
5958
5959 static int process_bad_block(ext2_filsys fs,
5960                       blk_t *block_nr,
5961                       e2_blkcnt_t blockcnt,
5962                       blk_t ref_block FSCK_ATTR((unused)),
5963                       int ref_offset FSCK_ATTR((unused)),
5964                       void *priv_data)
5965 {
5966         struct process_block_struct_1 *p;
5967         blk_t           blk = *block_nr;
5968         blk_t           first_block;
5969         dgrp_t          i;
5970         struct problem_context *pctx;
5971         e2fsck_t        ctx;
5972
5973         /*
5974          * Note: This function processes blocks for the bad blocks
5975          * inode, which is never compressed.  So we don't use HOLE_BLKADDR().
5976          */
5977
5978         if (!blk)
5979                 return 0;
5980
5981         p = (struct process_block_struct_1 *) priv_data;
5982         ctx = p->ctx;
5983         pctx = p->pctx;
5984
5985         pctx->ino = EXT2_BAD_INO;
5986         pctx->blk = blk;
5987         pctx->blkcount = blockcnt;
5988
5989         if ((blk < fs->super->s_first_data_block) ||
5990             (blk >= fs->super->s_blocks_count)) {
5991                 if (fix_problem(ctx, PR_1_BB_ILLEGAL_BLOCK_NUM, pctx)) {
5992                         *block_nr = 0;
5993                         return BLOCK_CHANGED;
5994                 } else
5995                         return 0;
5996         }
5997
5998         if (blockcnt < 0) {
5999                 if (ext2fs_test_block_bitmap(p->fs_meta_blocks, blk)) {
6000                         p->bbcheck = 1;
6001                         if (fix_problem(ctx, PR_1_BB_FS_BLOCK, pctx)) {
6002                                 *block_nr = 0;
6003                                 return BLOCK_CHANGED;
6004                         }
6005                 } else if (ext2fs_test_block_bitmap(ctx->block_found_map,
6006                                                     blk)) {
6007                         p->bbcheck = 1;
6008                         if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK,
6009                                         pctx)) {
6010                                 *block_nr = 0;
6011                                 return BLOCK_CHANGED;
6012                         }
6013                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6014                                 return BLOCK_ABORT;
6015                 } else
6016                         mark_block_used(ctx, blk);
6017                 return 0;
6018         }
6019 #if 0
6020         printf ("DEBUG: Marking %u as bad.\n", blk);
6021 #endif
6022         ctx->fs_badblocks_count++;
6023         /*
6024          * If the block is not used, then mark it as used and return.
6025          * If it is already marked as found, this must mean that
6026          * there's an overlap between the filesystem table blocks
6027          * (bitmaps and inode table) and the bad block list.
6028          */
6029         if (!ext2fs_test_block_bitmap(ctx->block_found_map, blk)) {
6030                 ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6031                 return 0;
6032         }
6033         /*
6034          * Try to find the where the filesystem block was used...
6035          */
6036         first_block = fs->super->s_first_data_block;
6037
6038         for (i = 0; i < fs->group_desc_count; i++ ) {
6039                 pctx->group = i;
6040                 pctx->blk = blk;
6041                 if (!ext2fs_bg_has_super(fs, i))
6042                         goto skip_super;
6043                 if (blk == first_block) {
6044                         if (i == 0) {
6045                                 if (fix_problem(ctx,
6046                                                 PR_1_BAD_PRIMARY_SUPERBLOCK,
6047                                                 pctx)) {
6048                                         *block_nr = 0;
6049                                         return BLOCK_CHANGED;
6050                                 }
6051                                 return 0;
6052                         }
6053                         fix_problem(ctx, PR_1_BAD_SUPERBLOCK, pctx);
6054                         return 0;
6055                 }
6056                 if ((blk > first_block) &&
6057                     (blk <= first_block + fs->desc_blocks)) {
6058                         if (i == 0) {
6059                                 pctx->blk = *block_nr;
6060                                 if (fix_problem(ctx,
6061                         PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR, pctx)) {
6062                                         *block_nr = 0;
6063                                         return BLOCK_CHANGED;
6064                                 }
6065                                 return 0;
6066                         }
6067                         fix_problem(ctx, PR_1_BAD_GROUP_DESCRIPTORS, pctx);
6068                         return 0;
6069                 }
6070         skip_super:
6071                 if (blk == fs->group_desc[i].bg_block_bitmap) {
6072                         if (fix_problem(ctx, PR_1_BB_BAD_BLOCK, pctx)) {
6073                                 ctx->invalid_block_bitmap_flag[i]++;
6074                                 ctx->invalid_bitmaps++;
6075                         }
6076                         return 0;
6077                 }
6078                 if (blk == fs->group_desc[i].bg_inode_bitmap) {
6079                         if (fix_problem(ctx, PR_1_IB_BAD_BLOCK, pctx)) {
6080                                 ctx->invalid_inode_bitmap_flag[i]++;
6081                                 ctx->invalid_bitmaps++;
6082                         }
6083                         return 0;
6084                 }
6085                 if ((blk >= fs->group_desc[i].bg_inode_table) &&
6086                     (blk < (fs->group_desc[i].bg_inode_table +
6087                             fs->inode_blocks_per_group))) {
6088                         /*
6089                          * If there are bad blocks in the inode table,
6090                          * the inode scan code will try to do
6091                          * something reasonable automatically.
6092                          */
6093                         return 0;
6094                 }
6095                 first_block += fs->super->s_blocks_per_group;
6096         }
6097         /*
6098          * If we've gotten to this point, then the only
6099          * possibility is that the bad block inode meta data
6100          * is using a bad block.
6101          */
6102         if ((blk == p->inode->i_block[EXT2_IND_BLOCK]) ||
6103             (blk == p->inode->i_block[EXT2_DIND_BLOCK]) ||
6104             (blk == p->inode->i_block[EXT2_TIND_BLOCK])) {
6105                 p->bbcheck = 1;
6106                 if (fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK, pctx)) {
6107                         *block_nr = 0;
6108                         return BLOCK_CHANGED;
6109                 }
6110                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6111                         return BLOCK_ABORT;
6112                 return 0;
6113         }
6114
6115         pctx->group = -1;
6116
6117         /* Warn user that the block wasn't claimed */
6118         fix_problem(ctx, PR_1_PROGERR_CLAIMED_BLOCK, pctx);
6119
6120         return 0;
6121 }
6122
6123 static void new_table_block(e2fsck_t ctx, blk_t first_block, int group,
6124                             const char *name, int num, blk_t *new_block)
6125 {
6126         ext2_filsys fs = ctx->fs;
6127         blk_t           old_block = *new_block;
6128         int             i;
6129         char            *buf;
6130         struct problem_context  pctx;
6131
6132         clear_problem_context(&pctx);
6133
6134         pctx.group = group;
6135         pctx.blk = old_block;
6136         pctx.str = name;
6137
6138         pctx.errcode = ext2fs_get_free_blocks(fs, first_block,
6139                         first_block + fs->super->s_blocks_per_group,
6140                                         num, ctx->block_found_map, new_block);
6141         if (pctx.errcode) {
6142                 pctx.num = num;
6143                 fix_problem(ctx, PR_1_RELOC_BLOCK_ALLOCATE, &pctx);
6144                 ext2fs_unmark_valid(fs);
6145                 return;
6146         }
6147         pctx.errcode = ext2fs_get_mem(fs->blocksize, &buf);
6148         if (pctx.errcode) {
6149                 fix_problem(ctx, PR_1_RELOC_MEMORY_ALLOCATE, &pctx);
6150                 ext2fs_unmark_valid(fs);
6151                 return;
6152         }
6153         ext2fs_mark_super_dirty(fs);
6154         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
6155         pctx.blk2 = *new_block;
6156         fix_problem(ctx, (old_block ? PR_1_RELOC_FROM_TO :
6157                           PR_1_RELOC_TO), &pctx);
6158         pctx.blk2 = 0;
6159         for (i = 0; i < num; i++) {
6160                 pctx.blk = i;
6161                 ext2fs_mark_block_bitmap(ctx->block_found_map, (*new_block)+i);
6162                 if (old_block) {
6163                         pctx.errcode = io_channel_read_blk(fs->io,
6164                                    old_block + i, 1, buf);
6165                         if (pctx.errcode)
6166                                 fix_problem(ctx, PR_1_RELOC_READ_ERR, &pctx);
6167                 } else
6168                         memset(buf, 0, fs->blocksize);
6169
6170                 pctx.blk = (*new_block) + i;
6171                 pctx.errcode = io_channel_write_blk(fs->io, pctx.blk,
6172                                               1, buf);
6173                 if (pctx.errcode)
6174                         fix_problem(ctx, PR_1_RELOC_WRITE_ERR, &pctx);
6175         }
6176         ext2fs_free_mem(&buf);
6177 }
6178
6179 /*
6180  * This routine gets called at the end of pass 1 if bad blocks are
6181  * detected in the superblock, group descriptors, inode_bitmaps, or
6182  * block bitmaps.  At this point, all of the blocks have been mapped
6183  * out, so we can try to allocate new block(s) to replace the bad
6184  * blocks.
6185  */
6186 static void handle_fs_bad_blocks(e2fsck_t ctx)
6187 {
6188         ext2_filsys fs = ctx->fs;
6189         dgrp_t          i;
6190         int             first_block = fs->super->s_first_data_block;
6191
6192         for (i = 0; i < fs->group_desc_count; i++) {
6193                 if (ctx->invalid_block_bitmap_flag[i]) {
6194                         new_table_block(ctx, first_block, i, _("block bitmap"),
6195                                         1, &fs->group_desc[i].bg_block_bitmap);
6196                 }
6197                 if (ctx->invalid_inode_bitmap_flag[i]) {
6198                         new_table_block(ctx, first_block, i, _("inode bitmap"),
6199                                         1, &fs->group_desc[i].bg_inode_bitmap);
6200                 }
6201                 if (ctx->invalid_inode_table_flag[i]) {
6202                         new_table_block(ctx, first_block, i, _("inode table"),
6203                                         fs->inode_blocks_per_group,
6204                                         &fs->group_desc[i].bg_inode_table);
6205                         ctx->flags |= E2F_FLAG_RESTART;
6206                 }
6207                 first_block += fs->super->s_blocks_per_group;
6208         }
6209         ctx->invalid_bitmaps = 0;
6210 }
6211
6212 /*
6213  * This routine marks all blocks which are used by the superblock,
6214  * group descriptors, inode bitmaps, and block bitmaps.
6215  */
6216 static void mark_table_blocks(e2fsck_t ctx)
6217 {
6218         ext2_filsys fs = ctx->fs;
6219         blk_t   block, b;
6220         dgrp_t  i;
6221         int     j;
6222         struct problem_context pctx;
6223
6224         clear_problem_context(&pctx);
6225
6226         block = fs->super->s_first_data_block;
6227         for (i = 0; i < fs->group_desc_count; i++) {
6228                 pctx.group = i;
6229
6230                 ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
6231
6232                 /*
6233                  * Mark the blocks used for the inode table
6234                  */
6235                 if (fs->group_desc[i].bg_inode_table) {
6236                         for (j = 0, b = fs->group_desc[i].bg_inode_table;
6237                              j < fs->inode_blocks_per_group;
6238                              j++, b++) {
6239                                 if (ext2fs_test_block_bitmap(ctx->block_found_map,
6240                                                              b)) {
6241                                         pctx.blk = b;
6242                                         if (fix_problem(ctx,
6243                                                 PR_1_ITABLE_CONFLICT, &pctx)) {
6244                                                 ctx->invalid_inode_table_flag[i]++;
6245                                                 ctx->invalid_bitmaps++;
6246                                         }
6247                                 } else {
6248                                     ext2fs_mark_block_bitmap(ctx->block_found_map,
6249                                                              b);
6250                                 }
6251                         }
6252                 }
6253
6254                 /*
6255                  * Mark block used for the block bitmap
6256                  */
6257                 if (fs->group_desc[i].bg_block_bitmap) {
6258                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
6259                                      fs->group_desc[i].bg_block_bitmap)) {
6260                                 pctx.blk = fs->group_desc[i].bg_block_bitmap;
6261                                 if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
6262                                         ctx->invalid_block_bitmap_flag[i]++;
6263                                         ctx->invalid_bitmaps++;
6264                                 }
6265                         } else {
6266                             ext2fs_mark_block_bitmap(ctx->block_found_map,
6267                                      fs->group_desc[i].bg_block_bitmap);
6268                     }
6269
6270                 }
6271                 /*
6272                  * Mark block used for the inode bitmap
6273                  */
6274                 if (fs->group_desc[i].bg_inode_bitmap) {
6275                         if (ext2fs_test_block_bitmap(ctx->block_found_map,
6276                                      fs->group_desc[i].bg_inode_bitmap)) {
6277                                 pctx.blk = fs->group_desc[i].bg_inode_bitmap;
6278                                 if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
6279                                         ctx->invalid_inode_bitmap_flag[i]++;
6280                                         ctx->invalid_bitmaps++;
6281                                 }
6282                         } else {
6283                             ext2fs_mark_block_bitmap(ctx->block_found_map,
6284                                      fs->group_desc[i].bg_inode_bitmap);
6285                         }
6286                 }
6287                 block += fs->super->s_blocks_per_group;
6288         }
6289 }
6290
6291 /*
6292  * Thes subroutines short circuits ext2fs_get_blocks and
6293  * ext2fs_check_directory; we use them since we already have the inode
6294  * structure, so there's no point in letting the ext2fs library read
6295  * the inode again.
6296  */
6297 static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
6298                                   blk_t *blocks)
6299 {
6300         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6301         int     i;
6302
6303         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
6304                 return EXT2_ET_CALLBACK_NOTHANDLED;
6305
6306         for (i=0; i < EXT2_N_BLOCKS; i++)
6307                 blocks[i] = ctx->stashed_inode->i_block[i];
6308         return 0;
6309 }
6310
6311 static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
6312                                   struct ext2_inode *inode)
6313 {
6314         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6315
6316         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
6317                 return EXT2_ET_CALLBACK_NOTHANDLED;
6318         *inode = *ctx->stashed_inode;
6319         return 0;
6320 }
6321
6322 static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
6323                             struct ext2_inode *inode)
6324 {
6325         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6326
6327         if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
6328                 *ctx->stashed_inode = *inode;
6329         return EXT2_ET_CALLBACK_NOTHANDLED;
6330 }
6331
6332 static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
6333 {
6334         e2fsck_t ctx = (e2fsck_t) fs->priv_data;
6335
6336         if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
6337                 return EXT2_ET_CALLBACK_NOTHANDLED;
6338
6339         if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
6340                 return EXT2_ET_NO_DIRECTORY;
6341         return 0;
6342 }
6343
6344 void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
6345 {
6346         ext2_filsys fs = ctx->fs;
6347
6348         if (bool) {
6349                 fs->get_blocks = pass1_get_blocks;
6350                 fs->check_directory = pass1_check_directory;
6351                 fs->read_inode = pass1_read_inode;
6352                 fs->write_inode = pass1_write_inode;
6353                 ctx->stashed_ino = 0;
6354         } else {
6355                 fs->get_blocks = 0;
6356                 fs->check_directory = 0;
6357                 fs->read_inode = 0;
6358                 fs->write_inode = 0;
6359         }
6360 }
6361
6362 /*
6363  * pass1b.c --- Pass #1b of e2fsck
6364  *
6365  * This file contains pass1B, pass1C, and pass1D of e2fsck.  They are
6366  * only invoked if pass 1 discovered blocks which are in use by more
6367  * than one inode.
6368  *
6369  * Pass1B scans the data blocks of all the inodes again, generating a
6370  * complete list of duplicate blocks and which inodes have claimed
6371  * them.
6372  *
6373  * Pass1C does a tree-traversal of the filesystem, to determine the
6374  * parent directories of these inodes.  This step is necessary so that
6375  * e2fsck can print out the pathnames of affected inodes.
6376  *
6377  * Pass1D is a reconciliation pass.  For each inode with duplicate
6378  * blocks, the user is prompted if s/he would like to clone the file
6379  * (so that the file gets a fresh copy of the duplicated blocks) or
6380  * simply to delete the file.
6381  *
6382  */
6383
6384
6385 /* Needed for architectures where sizeof(int) != sizeof(void *) */
6386 #define INT_TO_VOIDPTR(val)  ((void *)(intptr_t)(val))
6387 #define VOIDPTR_TO_INT(ptr)  ((int)(intptr_t)(ptr))
6388
6389 /* Define an extension to the ext2 library's block count information */
6390 #define BLOCK_COUNT_EXTATTR     (-5)
6391
6392 struct block_el {
6393         blk_t   block;
6394         struct block_el *next;
6395 };
6396
6397 struct inode_el {
6398         ext2_ino_t      inode;
6399         struct inode_el *next;
6400 };
6401
6402 struct dup_block {
6403         int             num_bad;
6404         struct inode_el *inode_list;
6405 };
6406
6407 /*
6408  * This structure stores information about a particular inode which
6409  * is sharing blocks with other inodes.  This information is collected
6410  * to display to the user, so that the user knows what files he or she
6411  * is dealing with, when trying to decide how to resolve the conflict
6412  * of multiply-claimed blocks.
6413  */
6414 struct dup_inode {
6415         ext2_ino_t              dir;
6416         int                     num_dupblocks;
6417         struct ext2_inode       inode;
6418         struct block_el         *block_list;
6419 };
6420
6421 static int process_pass1b_block(ext2_filsys fs, blk_t   *blocknr,
6422                                 e2_blkcnt_t blockcnt, blk_t ref_blk,
6423                                 int ref_offset, void *priv_data);
6424 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
6425                         struct dup_inode *dp, char *block_buf);
6426 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
6427                       struct dup_inode *dp, char* block_buf);
6428 static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
6429
6430 static void pass1b(e2fsck_t ctx, char *block_buf);
6431 static void pass1c(e2fsck_t ctx, char *block_buf);
6432 static void pass1d(e2fsck_t ctx, char *block_buf);
6433
6434 static int dup_inode_count = 0;
6435
6436 static dict_t blk_dict, ino_dict;
6437
6438 static ext2fs_inode_bitmap inode_dup_map;
6439
6440 static int dict_int_cmp(const void *a, const void *b)
6441 {
6442         intptr_t        ia, ib;
6443
6444         ia = (intptr_t)a;
6445         ib = (intptr_t)b;
6446
6447         return (ia-ib);
6448 }
6449
6450 /*
6451  * Add a duplicate block record
6452  */
6453 static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
6454                      struct ext2_inode *inode)
6455 {
6456         dnode_t *n;
6457         struct dup_block        *db;
6458         struct dup_inode        *di;
6459         struct block_el         *blk_el;
6460         struct inode_el         *ino_el;
6461
6462         n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
6463         if (n)
6464                 db = (struct dup_block *) dnode_get(n);
6465         else {
6466                 db = (struct dup_block *) e2fsck_allocate_memory(ctx,
6467                          sizeof(struct dup_block), "duplicate block header");
6468                 db->num_bad = 0;
6469                 db->inode_list = 0;
6470                 dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
6471         }
6472         ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
6473                          sizeof(struct inode_el), "inode element");
6474         ino_el->inode = ino;
6475         ino_el->next = db->inode_list;
6476         db->inode_list = ino_el;
6477         db->num_bad++;
6478
6479         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
6480         if (n)
6481                 di = (struct dup_inode *) dnode_get(n);
6482         else {
6483                 di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
6484                          sizeof(struct dup_inode), "duplicate inode header");
6485                 di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0 ;
6486                 di->num_dupblocks = 0;
6487                 di->block_list = 0;
6488                 di->inode = *inode;
6489                 dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
6490         }
6491         blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
6492                          sizeof(struct block_el), "block element");
6493         blk_el->block = blk;
6494         blk_el->next = di->block_list;
6495         di->block_list = blk_el;
6496         di->num_dupblocks++;
6497 }
6498
6499 /*
6500  * Free a duplicate inode record
6501  */
6502 static void inode_dnode_free(dnode_t *node)
6503 {
6504         struct dup_inode        *di;
6505         struct block_el         *p, *next;
6506
6507         di = (struct dup_inode *) dnode_get(node);
6508         for (p = di->block_list; p; p = next) {
6509                 next = p->next;
6510                 free(p);
6511         }
6512         free(node);
6513 }
6514
6515 /*
6516  * Free a duplicate block record
6517  */
6518 static void block_dnode_free(dnode_t *node)
6519 {
6520         struct dup_block        *db;
6521         struct inode_el         *p, *next;
6522
6523         db = (struct dup_block *) dnode_get(node);
6524         for (p = db->inode_list; p; p = next) {
6525                 next = p->next;
6526                 free(p);
6527         }
6528         free(node);
6529 }
6530
6531
6532 /*
6533  * Main procedure for handling duplicate blocks
6534  */
6535 void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
6536 {
6537         ext2_filsys             fs = ctx->fs;
6538         struct problem_context  pctx;
6539
6540         clear_problem_context(&pctx);
6541
6542         pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
6543                       _("multiply claimed inode map"), &inode_dup_map);
6544         if (pctx.errcode) {
6545                 fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
6546                 ctx->flags |= E2F_FLAG_ABORT;
6547                 return;
6548         }
6549
6550         dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
6551         dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
6552         dict_set_allocator(&ino_dict, inode_dnode_free);
6553         dict_set_allocator(&blk_dict, block_dnode_free);
6554
6555         pass1b(ctx, block_buf);
6556         pass1c(ctx, block_buf);
6557         pass1d(ctx, block_buf);
6558
6559         /*
6560          * Time to free all of the accumulated data structures that we
6561          * don't need anymore.
6562          */
6563         dict_free_nodes(&ino_dict);
6564         dict_free_nodes(&blk_dict);
6565 }
6566
6567 /*
6568  * Scan the inodes looking for inodes that contain duplicate blocks.
6569  */
6570 struct process_block_struct_1b {
6571         e2fsck_t        ctx;
6572         ext2_ino_t      ino;
6573         int             dup_blocks;
6574         struct ext2_inode *inode;
6575         struct problem_context *pctx;
6576 };
6577
6578 static void pass1b(e2fsck_t ctx, char *block_buf)
6579 {
6580         ext2_filsys fs = ctx->fs;
6581         ext2_ino_t ino;
6582         struct ext2_inode inode;
6583         ext2_inode_scan scan;
6584         struct process_block_struct_1b pb;
6585         struct problem_context pctx;
6586
6587         clear_problem_context(&pctx);
6588
6589         if (!(ctx->options & E2F_OPT_PREEN))
6590                 fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
6591         pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
6592                                               &scan);
6593         if (pctx.errcode) {
6594                 fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
6595                 ctx->flags |= E2F_FLAG_ABORT;
6596                 return;
6597         }
6598         ctx->stashed_inode = &inode;
6599         pb.ctx = ctx;
6600         pb.pctx = &pctx;
6601         pctx.str = "pass1b";
6602         while (1) {
6603                 pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
6604                 if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
6605                         continue;
6606                 if (pctx.errcode) {
6607                         fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
6608                         ctx->flags |= E2F_FLAG_ABORT;
6609                         return;
6610                 }
6611                 if (!ino)
6612                         break;
6613                 pctx.ino = ctx->stashed_ino = ino;
6614                 if ((ino != EXT2_BAD_INO) &&
6615                     !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
6616                         continue;
6617
6618                 pb.ino = ino;
6619                 pb.dup_blocks = 0;
6620                 pb.inode = &inode;
6621
6622                 if (ext2fs_inode_has_valid_blocks(&inode) ||
6623                     (ino == EXT2_BAD_INO))
6624                         pctx.errcode = ext2fs_block_iterate2(fs, ino,
6625                                      0, block_buf, process_pass1b_block, &pb);
6626                 if (inode.i_file_acl)
6627                         process_pass1b_block(fs, &inode.i_file_acl,
6628                                              BLOCK_COUNT_EXTATTR, 0, 0, &pb);
6629                 if (pb.dup_blocks) {
6630                         end_problem_latch(ctx, PR_LATCH_DBLOCK);
6631                         if (ino >= EXT2_FIRST_INODE(fs->super) ||
6632                             ino == EXT2_ROOT_INO)
6633                                 dup_inode_count++;
6634                 }
6635                 if (pctx.errcode)
6636                         fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
6637         }
6638         ext2fs_close_inode_scan(scan);
6639         e2fsck_use_inode_shortcuts(ctx, 0);
6640 }
6641
6642 static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
6643                                 blk_t   *block_nr,
6644                                 e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6645                                 blk_t ref_blk FSCK_ATTR((unused)),
6646                                 int ref_offset FSCK_ATTR((unused)),
6647                                 void *priv_data)
6648 {
6649         struct process_block_struct_1b *p;
6650         e2fsck_t ctx;
6651
6652         if (HOLE_BLKADDR(*block_nr))
6653                 return 0;
6654         p = (struct process_block_struct_1b *) priv_data;
6655         ctx = p->ctx;
6656
6657         if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
6658                 return 0;
6659
6660         /* OK, this is a duplicate block */
6661         if (p->ino != EXT2_BAD_INO) {
6662                 p->pctx->blk = *block_nr;
6663                 fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
6664         }
6665         p->dup_blocks++;
6666         ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
6667
6668         add_dupe(ctx, p->ino, *block_nr, p->inode);
6669
6670         return 0;
6671 }
6672
6673 /*
6674  * Pass 1c: Scan directories for inodes with duplicate blocks.  This
6675  * is used so that we can print pathnames when prompting the user for
6676  * what to do.
6677  */
6678 struct search_dir_struct {
6679         int             count;
6680         ext2_ino_t      first_inode;
6681         ext2_ino_t      max_inode;
6682 };
6683
6684 static int search_dirent_proc(ext2_ino_t dir, int entry,
6685                               struct ext2_dir_entry *dirent,
6686                               int offset FSCK_ATTR((unused)),
6687                               int blocksize FSCK_ATTR((unused)),
6688                               char *buf FSCK_ATTR((unused)),
6689                               void *priv_data)
6690 {
6691         struct search_dir_struct *sd;
6692         struct dup_inode        *p;
6693         dnode_t                 *n;
6694
6695         sd = (struct search_dir_struct *) priv_data;
6696
6697         if (dirent->inode > sd->max_inode)
6698                 /* Should abort this inode, but not everything */
6699                 return 0;
6700
6701         if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
6702             !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
6703                 return 0;
6704
6705         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
6706         if (!n)
6707                 return 0;
6708         p = (struct dup_inode *) dnode_get(n);
6709         p->dir = dir;
6710         sd->count--;
6711
6712         return(sd->count ? 0 : DIRENT_ABORT);
6713 }
6714
6715
6716 static void pass1c(e2fsck_t ctx, char *block_buf)
6717 {
6718         ext2_filsys fs = ctx->fs;
6719         struct search_dir_struct sd;
6720         struct problem_context pctx;
6721
6722         clear_problem_context(&pctx);
6723
6724         if (!(ctx->options & E2F_OPT_PREEN))
6725                 fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
6726
6727         /*
6728          * Search through all directories to translate inodes to names
6729          * (by searching for the containing directory for that inode.)
6730          */
6731         sd.count = dup_inode_count;
6732         sd.first_inode = EXT2_FIRST_INODE(fs->super);
6733         sd.max_inode = fs->super->s_inodes_count;
6734         ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
6735                                   search_dirent_proc, &sd);
6736 }
6737
6738 static void pass1d(e2fsck_t ctx, char *block_buf)
6739 {
6740         ext2_filsys fs = ctx->fs;
6741         struct dup_inode        *p, *t;
6742         struct dup_block        *q;
6743         ext2_ino_t              *shared, ino;
6744         int     shared_len;
6745         int     i;
6746         int     file_ok;
6747         int     meta_data = 0;
6748         struct problem_context pctx;
6749         dnode_t *n, *m;
6750         struct block_el *s;
6751         struct inode_el *r;
6752
6753         clear_problem_context(&pctx);
6754
6755         if (!(ctx->options & E2F_OPT_PREEN))
6756                 fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
6757         e2fsck_read_bitmaps(ctx);
6758
6759         pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
6760         fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
6761         shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
6762                                 sizeof(ext2_ino_t) * dict_count(&ino_dict),
6763                                 "Shared inode list");
6764         for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
6765                 p = (struct dup_inode *) dnode_get(n);
6766                 shared_len = 0;
6767                 file_ok = 1;
6768                 ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
6769                 if (ino == EXT2_BAD_INO)
6770                         continue;
6771
6772                 /*
6773                  * Find all of the inodes which share blocks with this
6774                  * one.  First we find all of the duplicate blocks
6775                  * belonging to this inode, and then search each block
6776                  * get the list of inodes, and merge them together.
6777                  */
6778                 for (s = p->block_list; s; s = s->next) {
6779                         m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
6780                         if (!m)
6781                                 continue; /* Should never happen... */
6782                         q = (struct dup_block *) dnode_get(m);
6783                         if (q->num_bad > 1)
6784                                 file_ok = 0;
6785                         if (check_if_fs_block(ctx, s->block)) {
6786                                 file_ok = 0;
6787                                 meta_data = 1;
6788                         }
6789
6790                         /*
6791                          * Add all inodes used by this block to the
6792                          * shared[] --- which is a unique list, so
6793                          * if an inode is already in shared[], don't
6794                          * add it again.
6795                          */
6796                         for (r = q->inode_list; r; r = r->next) {
6797                                 if (r->inode == ino)
6798                                         continue;
6799                                 for (i = 0; i < shared_len; i++)
6800                                         if (shared[i] == r->inode)
6801                                                 break;
6802                                 if (i == shared_len) {
6803                                         shared[shared_len++] = r->inode;
6804                                 }
6805                         }
6806                 }
6807
6808                 /*
6809                  * Report the inode that we are working on
6810                  */
6811                 pctx.inode = &p->inode;
6812                 pctx.ino = ino;
6813                 pctx.dir = p->dir;
6814                 pctx.blkcount = p->num_dupblocks;
6815                 pctx.num = meta_data ? shared_len+1 : shared_len;
6816                 fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
6817                 pctx.blkcount = 0;
6818                 pctx.num = 0;
6819
6820                 if (meta_data)
6821                         fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
6822
6823                 for (i = 0; i < shared_len; i++) {
6824                         m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
6825                         if (!m)
6826                                 continue; /* should never happen */
6827                         t = (struct dup_inode *) dnode_get(m);
6828                         /*
6829                          * Report the inode that we are sharing with
6830                          */
6831                         pctx.inode = &t->inode;
6832                         pctx.ino = shared[i];
6833                         pctx.dir = t->dir;
6834                         fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
6835                 }
6836                 if (file_ok) {
6837                         fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
6838                         continue;
6839                 }
6840                 if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
6841                         pctx.errcode = clone_file(ctx, ino, p, block_buf);
6842                         if (pctx.errcode)
6843                                 fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
6844                         else
6845                                 continue;
6846                 }
6847                 if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
6848                         delete_file(ctx, ino, p, block_buf);
6849                 else
6850                         ext2fs_unmark_valid(fs);
6851         }
6852         ext2fs_free_mem(&shared);
6853 }
6854
6855 /*
6856  * Drop the refcount on the dup_block structure, and clear the entry
6857  * in the block_dup_map if appropriate.
6858  */
6859 static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
6860 {
6861         p->num_bad--;
6862         if (p->num_bad <= 0 ||
6863             (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
6864                 ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
6865 }
6866
6867 static int delete_file_block(ext2_filsys fs,
6868                              blk_t      *block_nr,
6869                              e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6870                              blk_t ref_block FSCK_ATTR((unused)),
6871                              int ref_offset FSCK_ATTR((unused)),
6872                              void *priv_data)
6873 {
6874         struct process_block_struct_1b *pb;
6875         struct dup_block *p;
6876         dnode_t *n;
6877         e2fsck_t ctx;
6878
6879         pb = (struct process_block_struct_1b *) priv_data;
6880         ctx = pb->ctx;
6881
6882         if (HOLE_BLKADDR(*block_nr))
6883                 return 0;
6884
6885         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
6886                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
6887                 if (n) {
6888                         p = (struct dup_block *) dnode_get(n);
6889                         decrement_badcount(ctx, *block_nr, p);
6890                 } else
6891                         com_err("delete_file_block", 0,
6892                             _("internal error; can't find dup_blk for %d\n"),
6893                                 *block_nr);
6894         } else {
6895                 ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6896                 ext2fs_block_alloc_stats(fs, *block_nr, -1);
6897         }
6898
6899         return 0;
6900 }
6901
6902 static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
6903                         struct dup_inode *dp, char* block_buf)
6904 {
6905         ext2_filsys fs = ctx->fs;
6906         struct process_block_struct_1b pb;
6907         struct ext2_inode       inode;
6908         struct problem_context  pctx;
6909         unsigned int            count;
6910
6911         clear_problem_context(&pctx);
6912         pctx.ino = pb.ino = ino;
6913         pb.dup_blocks = dp->num_dupblocks;
6914         pb.ctx = ctx;
6915         pctx.str = "delete_file";
6916
6917         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
6918         if (ext2fs_inode_has_valid_blocks(&inode))
6919                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6920                                                      delete_file_block, &pb);
6921         if (pctx.errcode)
6922                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
6923         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6924         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6925         if (ctx->inode_bad_map)
6926                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6927         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6928
6929         /* Inode may have changed by block_iterate, so reread it */
6930         e2fsck_read_inode(ctx, ino, &inode, "delete_file");
6931         inode.i_links_count = 0;
6932         inode.i_dtime = time(0);
6933         if (inode.i_file_acl &&
6934             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6935                 count = 1;
6936                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6937                                                    block_buf, -1, &count);
6938                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6939                         pctx.errcode = 0;
6940                         count = 1;
6941                 }
6942                 if (pctx.errcode) {
6943                         pctx.blk = inode.i_file_acl;
6944                         fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
6945                 }
6946                 /*
6947                  * If the count is zero, then arrange to have the
6948                  * block deleted.  If the block is in the block_dup_map,
6949                  * also call delete_file_block since it will take care
6950                  * of keeping the accounting straight.
6951                  */
6952                 if ((count == 0) ||
6953                     ext2fs_test_block_bitmap(ctx->block_dup_map,
6954                                              inode.i_file_acl))
6955                         delete_file_block(fs, &inode.i_file_acl,
6956                                           BLOCK_COUNT_EXTATTR, 0, 0, &pb);
6957         }
6958         e2fsck_write_inode(ctx, ino, &inode, "delete_file");
6959 }
6960
6961 struct clone_struct {
6962         errcode_t       errcode;
6963         ext2_ino_t      dir;
6964         char    *buf;
6965         e2fsck_t ctx;
6966 };
6967
6968 static int clone_file_block(ext2_filsys fs,
6969                             blk_t       *block_nr,
6970                             e2_blkcnt_t blockcnt,
6971                             blk_t ref_block FSCK_ATTR((unused)),
6972                             int ref_offset FSCK_ATTR((unused)),
6973                             void *priv_data)
6974 {
6975         struct dup_block *p;
6976         blk_t   new_block;
6977         errcode_t       retval;
6978         struct clone_struct *cs = (struct clone_struct *) priv_data;
6979         dnode_t *n;
6980         e2fsck_t ctx;
6981
6982         ctx = cs->ctx;
6983
6984         if (HOLE_BLKADDR(*block_nr))
6985                 return 0;
6986
6987         if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
6988                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
6989                 if (n) {
6990                         p = (struct dup_block *) dnode_get(n);
6991                         retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
6992                                                   &new_block);
6993                         if (retval) {
6994                                 cs->errcode = retval;
6995                                 return BLOCK_ABORT;
6996                         }
6997                         if (cs->dir && (blockcnt >= 0)) {
6998                                 retval = ext2fs_set_dir_block(fs->dblist,
6999                                       cs->dir, new_block, blockcnt);
7000                                 if (retval) {
7001                                         cs->errcode = retval;
7002                                         return BLOCK_ABORT;
7003                                 }
7004                         }
7005 #if 0
7006                         printf("Cloning block %u to %u\n", *block_nr,
7007                                new_block);
7008 #endif
7009                         retval = io_channel_read_blk(fs->io, *block_nr, 1,
7010                                                      cs->buf);
7011                         if (retval) {
7012                                 cs->errcode = retval;
7013                                 return BLOCK_ABORT;
7014                         }
7015                         retval = io_channel_write_blk(fs->io, new_block, 1,
7016                                                       cs->buf);
7017                         if (retval) {
7018                                 cs->errcode = retval;
7019                                 return BLOCK_ABORT;
7020                         }
7021                         decrement_badcount(ctx, *block_nr, p);
7022                         *block_nr = new_block;
7023                         ext2fs_mark_block_bitmap(ctx->block_found_map,
7024                                                  new_block);
7025                         ext2fs_mark_block_bitmap(fs->block_map, new_block);
7026                         return BLOCK_CHANGED;
7027                 } else
7028                         com_err("clone_file_block", 0,
7029                             _("internal error; can't find dup_blk for %d\n"),
7030                                 *block_nr);
7031         }
7032         return 0;
7033 }
7034
7035 static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
7036                       struct dup_inode *dp, char* block_buf)
7037 {
7038         ext2_filsys fs = ctx->fs;
7039         errcode_t       retval;
7040         struct clone_struct cs;
7041         struct problem_context  pctx;
7042         blk_t           blk;
7043         dnode_t         *n;
7044         struct inode_el *ino_el;
7045         struct dup_block        *db;
7046         struct dup_inode        *di;
7047
7048         clear_problem_context(&pctx);
7049         cs.errcode = 0;
7050         cs.dir = 0;
7051         cs.ctx = ctx;
7052         retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
7053         if (retval)
7054                 return retval;
7055
7056         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
7057                 cs.dir = ino;
7058
7059         pctx.ino = ino;
7060         pctx.str = "clone_file";
7061         if (ext2fs_inode_has_valid_blocks(&dp->inode))
7062                 pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
7063                                                      clone_file_block, &cs);
7064         ext2fs_mark_bb_dirty(fs);
7065         if (pctx.errcode) {
7066                 fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
7067                 retval = pctx.errcode;
7068                 goto errout;
7069         }
7070         if (cs.errcode) {
7071                 com_err("clone_file", cs.errcode,
7072                         _("returned from clone_file_block"));
7073                 retval = cs.errcode;
7074                 goto errout;
7075         }
7076         /* The inode may have changed on disk, so we have to re-read it */
7077         e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
7078         blk = dp->inode.i_file_acl;
7079         if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
7080                                      BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
7081                     BLOCK_CHANGED)) {
7082                 e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
7083                 /*
7084                  * If we cloned the EA block, find all other inodes
7085                  * which refered to that EA block, and modify
7086                  * them to point to the new EA block.
7087                  */
7088                 n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
7089                 db = (struct dup_block *) dnode_get(n);
7090                 for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
7091                         if (ino_el->inode == ino)
7092                                 continue;
7093                         n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
7094                         di = (struct dup_inode *) dnode_get(n);
7095                         if (di->inode.i_file_acl == blk) {
7096                                 di->inode.i_file_acl = dp->inode.i_file_acl;
7097                                 e2fsck_write_inode(ctx, ino_el->inode,
7098                                            &di->inode, "clone file EA");
7099                                 decrement_badcount(ctx, blk, db);
7100                         }
7101                 }
7102         }
7103         retval = 0;
7104 errout:
7105         ext2fs_free_mem(&cs.buf);
7106         return retval;
7107 }
7108
7109 /*
7110  * This routine returns 1 if a block overlaps with one of the superblocks,
7111  * group descriptors, inode bitmaps, or block bitmaps.
7112  */
7113 static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
7114 {
7115         ext2_filsys fs = ctx->fs;
7116         blk_t   block;
7117         dgrp_t  i;
7118
7119         block = fs->super->s_first_data_block;
7120         for (i = 0; i < fs->group_desc_count; i++) {
7121
7122                 /* Check superblocks/block group descriptros */
7123                 if (ext2fs_bg_has_super(fs, i)) {
7124                         if (test_block >= block &&
7125                             (test_block <= block + fs->desc_blocks))
7126                                 return 1;
7127                 }
7128
7129                 /* Check the inode table */
7130                 if ((fs->group_desc[i].bg_inode_table) &&
7131                     (test_block >= fs->group_desc[i].bg_inode_table) &&
7132                     (test_block < (fs->group_desc[i].bg_inode_table +
7133                                    fs->inode_blocks_per_group)))
7134                         return 1;
7135
7136                 /* Check the bitmap blocks */
7137                 if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
7138                     (test_block == fs->group_desc[i].bg_inode_bitmap))
7139                         return 1;
7140
7141                 block += fs->super->s_blocks_per_group;
7142         }
7143         return 0;
7144 }
7145 /*
7146  * pass2.c --- check directory structure
7147  *
7148  * Pass 2 of e2fsck iterates through all active directory inodes, and
7149  * applies to following tests to each directory entry in the directory
7150  * blocks in the inodes:
7151  *
7152  *      - The length of the directory entry (rec_len) should be at
7153  *              least 8 bytes, and no more than the remaining space
7154  *              left in the directory block.
7155  *      - The length of the name in the directory entry (name_len)
7156  *              should be less than (rec_len - 8).
7157  *      - The inode number in the directory entry should be within
7158  *              legal bounds.
7159  *      - The inode number should refer to a in-use inode.
7160  *      - The first entry should be '.', and its inode should be
7161  *              the inode of the directory.
7162  *      - The second entry should be '..'.
7163  *
7164  * To minimize disk seek time, the directory blocks are processed in
7165  * sorted order of block numbers.
7166  *
7167  * Pass 2 also collects the following information:
7168  *      - The inode numbers of the subdirectories for each directory.
7169  *
7170  * Pass 2 relies on the following information from previous passes:
7171  *      - The directory information collected in pass 1.
7172  *      - The inode_used_map bitmap
7173  *      - The inode_bad_map bitmap
7174  *      - The inode_dir_map bitmap
7175  *
7176  * Pass 2 frees the following data structures
7177  *      - The inode_bad_map bitmap
7178  *      - The inode_reg_map bitmap
7179  */
7180
7181 /* #define DX_DEBUG */
7182
7183 /*
7184  * Keeps track of how many times an inode is referenced.
7185  */
7186 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
7187 static int check_dir_block(ext2_filsys fs,
7188                            struct ext2_db_entry *dir_blocks_info,
7189                            void *priv_data);
7190 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
7191                               struct problem_context *pctx);
7192 static int update_dir_block(ext2_filsys fs,
7193                             blk_t       *block_nr,
7194                             e2_blkcnt_t blockcnt,
7195                             blk_t       ref_block,
7196                             int         ref_offset,
7197                             void        *priv_data);
7198 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
7199 static int htree_depth(struct dx_dir_info *dx_dir,
7200                        struct dx_dirblock_info *dx_db);
7201 static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b);
7202
7203 struct check_dir_struct {
7204         char *buf;
7205         struct problem_context  pctx;
7206         int     count, max;
7207         e2fsck_t ctx;
7208 };
7209
7210 static void e2fsck_pass2(e2fsck_t ctx)
7211 {
7212         struct ext2_super_block *sb = ctx->fs->super;
7213         struct problem_context  pctx;
7214         ext2_filsys             fs = ctx->fs;
7215         char                    *buf;
7216 #ifdef RESOURCE_TRACK
7217         struct resource_track   rtrack;
7218 #endif
7219         struct dir_info         *dir;
7220         struct check_dir_struct cd;
7221         struct dx_dir_info      *dx_dir;
7222         struct dx_dirblock_info *dx_db, *dx_parent;
7223         int                     b;
7224         int                     i, depth;
7225         problem_t               code;
7226         int                     bad_dir;
7227
7228 #ifdef RESOURCE_TRACK
7229         init_resource_track(&rtrack);
7230 #endif
7231
7232         clear_problem_context(&cd.pctx);
7233
7234 #ifdef MTRACE
7235         mtrace_print("Pass 2");
7236 #endif
7237
7238         if (!(ctx->options & E2F_OPT_PREEN))
7239                 fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
7240
7241         cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
7242                                                 0, ctx->inode_link_info,
7243                                                 &ctx->inode_count);
7244         if (cd.pctx.errcode) {
7245                 fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
7246                 ctx->flags |= E2F_FLAG_ABORT;
7247                 return;
7248         }
7249         buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
7250                                               "directory scan buffer");
7251
7252         /*
7253          * Set up the parent pointer for the root directory, if
7254          * present.  (If the root directory is not present, we will
7255          * create it in pass 3.)
7256          */
7257         dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
7258         if (dir)
7259                 dir->parent = EXT2_ROOT_INO;
7260
7261         cd.buf = buf;
7262         cd.ctx = ctx;
7263         cd.count = 1;
7264         cd.max = ext2fs_dblist_count(fs->dblist);
7265
7266         if (ctx->progress)
7267                 (void) (ctx->progress)(ctx, 2, 0, cd.max);
7268
7269         if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
7270                 ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
7271
7272         cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
7273                                                 &cd);
7274         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7275                 return;
7276         if (cd.pctx.errcode) {
7277                 fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
7278                 ctx->flags |= E2F_FLAG_ABORT;
7279                 return;
7280         }
7281
7282 #ifdef ENABLE_HTREE
7283         for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
7284                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7285                         return;
7286                 if (dx_dir->numblocks == 0)
7287                         continue;
7288                 clear_problem_context(&pctx);
7289                 bad_dir = 0;
7290                 pctx.dir = dx_dir->ino;
7291                 dx_db = dx_dir->dx_block;
7292                 if (dx_db->flags & DX_FLAG_REFERENCED)
7293                         dx_db->flags |= DX_FLAG_DUP_REF;
7294                 else
7295                         dx_db->flags |= DX_FLAG_REFERENCED;
7296                 /*
7297                  * Find all of the first and last leaf blocks, and
7298                  * update their parent's min and max hash values
7299                  */
7300                 for (b=0, dx_db = dx_dir->dx_block;
7301                      b < dx_dir->numblocks;
7302                      b++, dx_db++) {
7303                         if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
7304                             !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
7305                                 continue;
7306                         dx_parent = &dx_dir->dx_block[dx_db->parent];
7307                         /*
7308                          * XXX Make sure dx_parent->min_hash > dx_db->min_hash
7309                          */
7310                         if (dx_db->flags & DX_FLAG_FIRST)
7311                                 dx_parent->min_hash = dx_db->min_hash;
7312                         /*
7313                          * XXX Make sure dx_parent->max_hash < dx_db->max_hash
7314                          */
7315                         if (dx_db->flags & DX_FLAG_LAST)
7316                                 dx_parent->max_hash = dx_db->max_hash;
7317                 }
7318
7319                 for (b=0, dx_db = dx_dir->dx_block;
7320                      b < dx_dir->numblocks;
7321                      b++, dx_db++) {
7322                         pctx.blkcount = b;
7323                         pctx.group = dx_db->parent;
7324                         code = 0;
7325                         if (!(dx_db->flags & DX_FLAG_FIRST) &&
7326                             (dx_db->min_hash < dx_db->node_min_hash)) {
7327                                 pctx.blk = dx_db->min_hash;
7328                                 pctx.blk2 = dx_db->node_min_hash;
7329                                 code = PR_2_HTREE_MIN_HASH;
7330                                 fix_problem(ctx, code, &pctx);
7331                                 bad_dir++;
7332                         }
7333                         if (dx_db->type == DX_DIRBLOCK_LEAF) {
7334                                 depth = htree_depth(dx_dir, dx_db);
7335                                 if (depth != dx_dir->depth) {
7336                                         code = PR_2_HTREE_BAD_DEPTH;
7337                                         fix_problem(ctx, code, &pctx);
7338                                         bad_dir++;
7339                                 }
7340                         }
7341                         /*
7342                          * This test doesn't apply for the root block
7343                          * at block #0
7344                          */
7345                         if (b &&
7346                             (dx_db->max_hash > dx_db->node_max_hash)) {
7347                                 pctx.blk = dx_db->max_hash;
7348                                 pctx.blk2 = dx_db->node_max_hash;
7349                                 code = PR_2_HTREE_MAX_HASH;
7350                                 fix_problem(ctx, code, &pctx);
7351                                 bad_dir++;
7352                         }
7353                         if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
7354                                 code = PR_2_HTREE_NOTREF;
7355                                 fix_problem(ctx, code, &pctx);
7356                                 bad_dir++;
7357                         } else if (dx_db->flags & DX_FLAG_DUP_REF) {
7358                                 code = PR_2_HTREE_DUPREF;
7359                                 fix_problem(ctx, code, &pctx);
7360                                 bad_dir++;
7361                         }
7362                         if (code == 0)
7363                                 continue;
7364                 }
7365                 if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
7366                         clear_htree(ctx, dx_dir->ino);
7367                         dx_dir->numblocks = 0;
7368                 }
7369         }
7370 #endif
7371         ext2fs_free_mem(&buf);
7372         ext2fs_free_dblist(fs->dblist);
7373
7374         if (ctx->inode_bad_map) {
7375                 ext2fs_free_inode_bitmap(ctx->inode_bad_map);
7376                 ctx->inode_bad_map = 0;
7377         }
7378         if (ctx->inode_reg_map) {
7379                 ext2fs_free_inode_bitmap(ctx->inode_reg_map);
7380                 ctx->inode_reg_map = 0;
7381         }
7382
7383         clear_problem_context(&pctx);
7384         if (ctx->large_files) {
7385                 if (!(sb->s_feature_ro_compat &
7386                       EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
7387                     fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
7388                         sb->s_feature_ro_compat |=
7389                                 EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
7390                         ext2fs_mark_super_dirty(fs);
7391                 }
7392                 if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
7393                     fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
7394                         ext2fs_update_dynamic_rev(fs);
7395                         ext2fs_mark_super_dirty(fs);
7396                 }
7397         } else if (!ctx->large_files &&
7398             (sb->s_feature_ro_compat &
7399               EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
7400                 if (fs->flags & EXT2_FLAG_RW) {
7401                         sb->s_feature_ro_compat &=
7402                                 ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
7403                         ext2fs_mark_super_dirty(fs);
7404                 }
7405         }
7406
7407 #ifdef RESOURCE_TRACK
7408         if (ctx->options & E2F_OPT_TIME2) {
7409                 e2fsck_clear_progbar(ctx);
7410                 print_resource_track(_("Pass 2"), &rtrack);
7411         }
7412 #endif
7413 }
7414
7415 #define MAX_DEPTH 32000
7416 static int htree_depth(struct dx_dir_info *dx_dir,
7417                        struct dx_dirblock_info *dx_db)
7418 {
7419         int     depth = 0;
7420
7421         while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
7422                 dx_db = &dx_dir->dx_block[dx_db->parent];
7423                 depth++;
7424         }
7425         return depth;
7426 }
7427
7428 static int dict_de_cmp(const void *a, const void *b)
7429 {
7430         const struct ext2_dir_entry *de_a, *de_b;
7431         int     a_len, b_len;
7432
7433         de_a = (const struct ext2_dir_entry *) a;
7434         a_len = de_a->name_len & 0xFF;
7435         de_b = (const struct ext2_dir_entry *) b;
7436         b_len = de_b->name_len & 0xFF;
7437
7438         if (a_len != b_len)
7439                 return (a_len - b_len);
7440
7441         return strncmp(de_a->name, de_b->name, a_len);
7442 }
7443
7444 /*
7445  * This is special sort function that makes sure that directory blocks
7446  * with a dirblock of zero are sorted to the beginning of the list.
7447  * This guarantees that the root node of the htree directories are
7448  * processed first, so we know what hash version to use.
7449  */
7450 static EXT2_QSORT_TYPE special_dir_block_cmp(const void *a, const void *b)
7451 {
7452         const struct ext2_db_entry *db_a =
7453                 (const struct ext2_db_entry *) a;
7454         const struct ext2_db_entry *db_b =
7455                 (const struct ext2_db_entry *) b;
7456
7457         if (db_a->blockcnt && !db_b->blockcnt)
7458                 return 1;
7459
7460         if (!db_a->blockcnt && db_b->blockcnt)
7461                 return -1;
7462
7463         if (db_a->blk != db_b->blk)
7464                 return (int) (db_a->blk - db_b->blk);
7465
7466         if (db_a->ino != db_b->ino)
7467                 return (int) (db_a->ino - db_b->ino);
7468
7469         return (int) (db_a->blockcnt - db_b->blockcnt);
7470 }
7471
7472
7473 /*
7474  * Make sure the first entry in the directory is '.', and that the
7475  * directory entry is sane.
7476  */
7477 static int check_dot(e2fsck_t ctx,
7478                      struct ext2_dir_entry *dirent,
7479                      ext2_ino_t ino, struct problem_context *pctx)
7480 {
7481         struct ext2_dir_entry *nextdir;
7482         int     status = 0;
7483         int     created = 0;
7484         int     new_len;
7485         int     problem = 0;
7486
7487         if (!dirent->inode)
7488                 problem = PR_2_MISSING_DOT;
7489         else if (((dirent->name_len & 0xFF) != 1) ||
7490                  (dirent->name[0] != '.'))
7491                 problem = PR_2_1ST_NOT_DOT;
7492         else if (dirent->name[1] != '\0')
7493                 problem = PR_2_DOT_NULL_TERM;
7494
7495         if (problem) {
7496                 if (fix_problem(ctx, problem, pctx)) {
7497                         if (dirent->rec_len < 12)
7498                                 dirent->rec_len = 12;
7499                         dirent->inode = ino;
7500                         dirent->name_len = 1;
7501                         dirent->name[0] = '.';
7502                         dirent->name[1] = '\0';
7503                         status = 1;
7504                         created = 1;
7505                 }
7506         }
7507         if (dirent->inode != ino) {
7508                 if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
7509                         dirent->inode = ino;
7510                         status = 1;
7511                 }
7512         }
7513         if (dirent->rec_len > 12) {
7514                 new_len = dirent->rec_len - 12;
7515                 if (new_len > 12) {
7516                         if (created ||
7517                             fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
7518                                 nextdir = (struct ext2_dir_entry *)
7519                                         ((char *) dirent + 12);
7520                                 dirent->rec_len = 12;
7521                                 nextdir->rec_len = new_len;
7522                                 nextdir->inode = 0;
7523                                 nextdir->name_len = 0;
7524                                 status = 1;
7525                         }
7526                 }
7527         }
7528         return status;
7529 }
7530
7531 /*
7532  * Make sure the second entry in the directory is '..', and that the
7533  * directory entry is sane.  We do not check the inode number of '..'
7534  * here; this gets done in pass 3.
7535  */
7536 static int check_dotdot(e2fsck_t ctx,
7537                         struct ext2_dir_entry *dirent,
7538                         struct dir_info *dir, struct problem_context *pctx)
7539 {
7540         int             problem = 0;
7541
7542         if (!dirent->inode)
7543                 problem = PR_2_MISSING_DOT_DOT;
7544         else if (((dirent->name_len & 0xFF) != 2) ||
7545                  (dirent->name[0] != '.') ||
7546                  (dirent->name[1] != '.'))
7547                 problem = PR_2_2ND_NOT_DOT_DOT;
7548         else if (dirent->name[2] != '\0')
7549                 problem = PR_2_DOT_DOT_NULL_TERM;
7550
7551         if (problem) {
7552                 if (fix_problem(ctx, problem, pctx)) {
7553                         if (dirent->rec_len < 12)
7554                                 dirent->rec_len = 12;
7555                         /*
7556                          * Note: we don't have the parent inode just
7557                          * yet, so we will fill it in with the root
7558                          * inode.  This will get fixed in pass 3.
7559                          */
7560                         dirent->inode = EXT2_ROOT_INO;
7561                         dirent->name_len = 2;
7562                         dirent->name[0] = '.';
7563                         dirent->name[1] = '.';
7564                         dirent->name[2] = '\0';
7565                         return 1;
7566                 }
7567                 return 0;
7568         }
7569         dir->dotdot = dirent->inode;
7570         return 0;
7571 }
7572
7573 /*
7574  * Check to make sure a directory entry doesn't contain any illegal
7575  * characters.
7576  */
7577 static int check_name(e2fsck_t ctx,
7578                       struct ext2_dir_entry *dirent,
7579                       struct problem_context *pctx)
7580 {
7581         int     i;
7582         int     fixup = -1;
7583         int     ret = 0;
7584
7585         for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
7586                 if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
7587                         if (fixup < 0) {
7588                                 fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
7589                         }
7590                         if (fixup) {
7591                                 dirent->name[i] = '.';
7592                                 ret = 1;
7593                         }
7594                 }
7595         }
7596         return ret;
7597 }
7598
7599 /*
7600  * Check the directory filetype (if present)
7601  */
7602
7603 /*
7604  * Given a mode, return the ext2 file type
7605  */
7606 static int ext2_file_type(unsigned int mode)
7607 {
7608         if (LINUX_S_ISREG(mode))
7609                 return EXT2_FT_REG_FILE;
7610
7611         if (LINUX_S_ISDIR(mode))
7612                 return EXT2_FT_DIR;
7613
7614         if (LINUX_S_ISCHR(mode))
7615                 return EXT2_FT_CHRDEV;
7616
7617         if (LINUX_S_ISBLK(mode))
7618                 return EXT2_FT_BLKDEV;
7619
7620         if (LINUX_S_ISLNK(mode))
7621                 return EXT2_FT_SYMLINK;
7622
7623         if (LINUX_S_ISFIFO(mode))
7624                 return EXT2_FT_FIFO;
7625
7626         if (LINUX_S_ISSOCK(mode))
7627                 return EXT2_FT_SOCK;
7628
7629         return 0;
7630 }
7631
7632 static _INLINE_ int check_filetype(e2fsck_t ctx,
7633                                    struct ext2_dir_entry *dirent,
7634                                    struct problem_context *pctx)
7635 {
7636         int     filetype = dirent->name_len >> 8;
7637         int     should_be = EXT2_FT_UNKNOWN;
7638         struct ext2_inode       inode;
7639
7640         if (!(ctx->fs->super->s_feature_incompat &
7641               EXT2_FEATURE_INCOMPAT_FILETYPE)) {
7642                 if (filetype == 0 ||
7643                     !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
7644                         return 0;
7645                 dirent->name_len = dirent->name_len & 0xFF;
7646                 return 1;
7647         }
7648
7649         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
7650                 should_be = EXT2_FT_DIR;
7651         } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
7652                                             dirent->inode)) {
7653                 should_be = EXT2_FT_REG_FILE;
7654         } else if (ctx->inode_bad_map &&
7655                    ext2fs_test_inode_bitmap(ctx->inode_bad_map,
7656                                             dirent->inode))
7657                 should_be = 0;
7658         else {
7659                 e2fsck_read_inode(ctx, dirent->inode, &inode,
7660                                   "check_filetype");
7661                 should_be = ext2_file_type(inode.i_mode);
7662         }
7663         if (filetype == should_be)
7664                 return 0;
7665         pctx->num = should_be;
7666
7667         if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
7668                         pctx) == 0)
7669                 return 0;
7670
7671         dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
7672         return 1;
7673 }
7674
7675 #ifdef ENABLE_HTREE
7676 static void parse_int_node(ext2_filsys fs,
7677                            struct ext2_db_entry *db,
7678                            struct check_dir_struct *cd,
7679                            struct dx_dir_info   *dx_dir,
7680                            char *block_buf)
7681 {
7682         struct          ext2_dx_root_info  *root;
7683         struct          ext2_dx_entry *ent;
7684         struct          ext2_dx_countlimit *limit;
7685         struct dx_dirblock_info *dx_db;
7686         int             i, expect_limit, count;
7687         blk_t           blk;
7688         ext2_dirhash_t  min_hash = 0xffffffff;
7689         ext2_dirhash_t  max_hash = 0;
7690         ext2_dirhash_t  hash = 0, prev_hash;
7691
7692         if (db->blockcnt == 0) {
7693                 root = (struct ext2_dx_root_info *) (block_buf + 24);
7694
7695 #ifdef DX_DEBUG
7696                 printf("Root node dump:\n");
7697                 printf("\t Reserved zero: %d\n", root->reserved_zero);
7698                 printf("\t Hash Version: %d\n", root->hash_version);
7699                 printf("\t Info length: %d\n", root->info_length);
7700                 printf("\t Indirect levels: %d\n", root->indirect_levels);
7701                 printf("\t Flags: %d\n", root->unused_flags);
7702 #endif
7703
7704                 ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
7705         } else {
7706                 ent = (struct ext2_dx_entry *) (block_buf+8);
7707         }
7708         limit = (struct ext2_dx_countlimit *) ent;
7709
7710 #ifdef DX_DEBUG
7711         printf("Number of entries (count): %d\n",
7712                ext2fs_le16_to_cpu(limit->count));
7713         printf("Number of entries (limit): %d\n",
7714                ext2fs_le16_to_cpu(limit->limit));
7715 #endif
7716
7717         count = ext2fs_le16_to_cpu(limit->count);
7718         expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
7719                 sizeof(struct ext2_dx_entry);
7720         if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
7721                 cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
7722                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
7723                         goto clear_and_exit;
7724         }
7725         if (count > expect_limit) {
7726                 cd->pctx.num = count;
7727                 if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
7728                         goto clear_and_exit;
7729                 count = expect_limit;
7730         }
7731
7732         for (i=0; i < count; i++) {
7733                 prev_hash = hash;
7734                 hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
7735 #ifdef DX_DEBUG
7736                 printf("Entry #%d: Hash 0x%08x, block %d\n", i,
7737                        hash, ext2fs_le32_to_cpu(ent[i].block));
7738 #endif
7739                 blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
7740                 /* Check to make sure the block is valid */
7741                 if (blk > (blk_t) dx_dir->numblocks) {
7742                         cd->pctx.blk = blk;
7743                         if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
7744                                         &cd->pctx))
7745                                 goto clear_and_exit;
7746                 }
7747                 if (hash < prev_hash &&
7748                     fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
7749                         goto clear_and_exit;
7750                 dx_db = &dx_dir->dx_block[blk];
7751                 if (dx_db->flags & DX_FLAG_REFERENCED) {
7752                         dx_db->flags |= DX_FLAG_DUP_REF;
7753                 } else {
7754                         dx_db->flags |= DX_FLAG_REFERENCED;
7755                         dx_db->parent = db->blockcnt;
7756                 }
7757                 if (hash < min_hash)
7758                         min_hash = hash;
7759                 if (hash > max_hash)
7760                         max_hash = hash;
7761                 dx_db->node_min_hash = hash;
7762                 if ((i+1) < count)
7763                         dx_db->node_max_hash =
7764                           ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
7765                 else {
7766                         dx_db->node_max_hash = 0xfffffffe;
7767                         dx_db->flags |= DX_FLAG_LAST;
7768                 }
7769                 if (i == 0)
7770                         dx_db->flags |= DX_FLAG_FIRST;
7771         }
7772 #ifdef DX_DEBUG
7773         printf("Blockcnt = %d, min hash 0x%08x, max hash 0x%08x\n",
7774                db->blockcnt, min_hash, max_hash);
7775 #endif
7776         dx_db = &dx_dir->dx_block[db->blockcnt];
7777         dx_db->min_hash = min_hash;
7778         dx_db->max_hash = max_hash;
7779         return;
7780
7781 clear_and_exit:
7782         clear_htree(cd->ctx, cd->pctx.ino);
7783         dx_dir->numblocks = 0;
7784 }
7785 #endif /* ENABLE_HTREE */
7786
7787 /*
7788  * Given a busted directory, try to salvage it somehow.
7789  *
7790  */
7791 static void salvage_directory(ext2_filsys fs,
7792                               struct ext2_dir_entry *dirent,
7793                               struct ext2_dir_entry *prev,
7794                               unsigned int *offset)
7795 {
7796         char    *cp = (char *) dirent;
7797         int left = fs->blocksize - *offset - dirent->rec_len;
7798         int name_len = dirent->name_len & 0xFF;
7799
7800         /*
7801          * Special case of directory entry of size 8: copy what's left
7802          * of the directory block up to cover up the invalid hole.
7803          */
7804         if ((left >= 12) && (dirent->rec_len == 8)) {
7805                 memmove(cp, cp+8, left);
7806                 memset(cp + left, 0, 8);
7807                 return;
7808         }
7809         /*
7810          * If the directory entry overruns the end of the directory
7811          * block, and the name is small enough to fit, then adjust the
7812          * record length.
7813          */
7814         if ((left < 0) &&
7815             (name_len + 8 <= dirent->rec_len + left) &&
7816             dirent->inode <= fs->super->s_inodes_count &&
7817             strnlen(dirent->name, name_len) == name_len) {
7818                 dirent->rec_len += left;
7819                 return;
7820         }
7821         /*
7822          * If the directory entry is a multiple of four, so it is
7823          * valid, let the previous directory entry absorb the invalid
7824          * one.
7825          */
7826         if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
7827                 prev->rec_len += dirent->rec_len;
7828                 *offset += dirent->rec_len;
7829                 return;
7830         }
7831         /*
7832          * Default salvage method --- kill all of the directory
7833          * entries for the rest of the block.  We will either try to
7834          * absorb it into the previous directory entry, or create a
7835          * new empty directory entry the rest of the directory block.
7836          */
7837         if (prev) {
7838                 prev->rec_len += fs->blocksize - *offset;
7839                 *offset = fs->blocksize;
7840         } else {
7841                 dirent->rec_len = fs->blocksize - *offset;
7842                 dirent->name_len = 0;
7843                 dirent->inode = 0;
7844         }
7845 }
7846
7847 static int check_dir_block(ext2_filsys fs,
7848                            struct ext2_db_entry *db,
7849                            void *priv_data)
7850 {
7851         struct dir_info         *subdir, *dir;
7852         struct dx_dir_info      *dx_dir;
7853 #ifdef ENABLE_HTREE
7854         struct dx_dirblock_info *dx_db = 0;
7855 #endif /* ENABLE_HTREE */
7856         struct ext2_dir_entry   *dirent, *prev;
7857         ext2_dirhash_t          hash;
7858         unsigned int            offset = 0;
7859         int                     dir_modified = 0;
7860         int                     dot_state;
7861         blk_t                   block_nr = db->blk;
7862         ext2_ino_t              ino = db->ino;
7863         __u16                   links;
7864         struct check_dir_struct *cd;
7865         char                    *buf;
7866         e2fsck_t                ctx;
7867         int                     problem;
7868         struct ext2_dx_root_info *root;
7869         struct ext2_dx_countlimit *limit;
7870         static dict_t de_dict;
7871         struct problem_context  pctx;
7872         int     dups_found = 0;
7873
7874         cd = (struct check_dir_struct *) priv_data;
7875         buf = cd->buf;
7876         ctx = cd->ctx;
7877
7878         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7879                 return DIRENT_ABORT;
7880
7881         if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
7882                 return DIRENT_ABORT;
7883
7884         /*
7885          * Make sure the inode is still in use (could have been
7886          * deleted in the duplicate/bad blocks pass.
7887          */
7888         if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
7889                 return 0;
7890
7891         cd->pctx.ino = ino;
7892         cd->pctx.blk = block_nr;
7893         cd->pctx.blkcount = db->blockcnt;
7894         cd->pctx.ino2 = 0;
7895         cd->pctx.dirent = 0;
7896         cd->pctx.num = 0;
7897
7898         if (db->blk == 0) {
7899                 if (allocate_dir_block(ctx, db, &cd->pctx))
7900                         return 0;
7901                 block_nr = db->blk;
7902         }
7903
7904         if (db->blockcnt)
7905                 dot_state = 2;
7906         else
7907                 dot_state = 0;
7908
7909         if (ctx->dirs_to_hash &&
7910             ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
7911                 dups_found++;
7912
7913 #if 0
7914         printf("In process_dir_block block %lu, #%d, inode %lu\n", block_nr,
7915                db->blockcnt, ino);
7916 #endif
7917
7918         cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
7919         if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
7920                 cd->pctx.errcode = 0; /* We'll handle this ourselves */
7921         if (cd->pctx.errcode) {
7922                 if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
7923                         ctx->flags |= E2F_FLAG_ABORT;
7924                         return DIRENT_ABORT;
7925                 }
7926                 memset(buf, 0, fs->blocksize);
7927         }
7928 #ifdef ENABLE_HTREE
7929         dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
7930         if (dx_dir && dx_dir->numblocks) {
7931                 if (db->blockcnt >= dx_dir->numblocks) {
7932                         printf("XXX should never happen!!!\n");
7933                         abort();
7934                 }
7935                 dx_db = &dx_dir->dx_block[db->blockcnt];
7936                 dx_db->type = DX_DIRBLOCK_LEAF;
7937                 dx_db->phys = block_nr;
7938                 dx_db->min_hash = ~0;
7939                 dx_db->max_hash = 0;
7940
7941                 dirent = (struct ext2_dir_entry *) buf;
7942                 limit = (struct ext2_dx_countlimit *) (buf+8);
7943                 if (db->blockcnt == 0) {
7944                         root = (struct ext2_dx_root_info *) (buf + 24);
7945                         dx_db->type = DX_DIRBLOCK_ROOT;
7946                         dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
7947                         if ((root->reserved_zero ||
7948                              root->info_length < 8 ||
7949                              root->indirect_levels > 1) &&
7950                             fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
7951                                 clear_htree(ctx, ino);
7952                                 dx_dir->numblocks = 0;
7953                                 dx_db = 0;
7954                         }
7955                         dx_dir->hashversion = root->hash_version;
7956                         dx_dir->depth = root->indirect_levels + 1;
7957                 } else if ((dirent->inode == 0) &&
7958                            (dirent->rec_len == fs->blocksize) &&
7959                            (dirent->name_len == 0) &&
7960                            (ext2fs_le16_to_cpu(limit->limit) ==
7961                             ((fs->blocksize-8) /
7962                              sizeof(struct ext2_dx_entry))))
7963                         dx_db->type = DX_DIRBLOCK_NODE;
7964         }
7965 #endif /* ENABLE_HTREE */
7966
7967         dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
7968         prev = 0;
7969         do {
7970                 problem = 0;
7971                 dirent = (struct ext2_dir_entry *) (buf + offset);
7972                 cd->pctx.dirent = dirent;
7973                 cd->pctx.num = offset;
7974                 if (((offset + dirent->rec_len) > fs->blocksize) ||
7975                     (dirent->rec_len < 12) ||
7976                     ((dirent->rec_len % 4) != 0) ||
7977                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
7978                         if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
7979                                 salvage_directory(fs, dirent, prev, &offset);
7980                                 dir_modified++;
7981                                 continue;
7982                         } else
7983                                 goto abort_free_dict;
7984                 }
7985                 if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
7986                         if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
7987                                 dirent->name_len = EXT2_NAME_LEN;
7988                                 dir_modified++;
7989                         }
7990                 }
7991
7992                 if (dot_state == 0) {
7993                         if (check_dot(ctx, dirent, ino, &cd->pctx))
7994                                 dir_modified++;
7995                 } else if (dot_state == 1) {
7996                         dir = e2fsck_get_dir_info(ctx, ino);
7997                         if (!dir) {
7998                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
7999                                 goto abort_free_dict;
8000                         }
8001                         if (check_dotdot(ctx, dirent, dir, &cd->pctx))
8002                                 dir_modified++;
8003                 } else if (dirent->inode == ino) {
8004                         problem = PR_2_LINK_DOT;
8005                         if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
8006                                 dirent->inode = 0;
8007                                 dir_modified++;
8008                                 goto next;
8009                         }
8010                 }
8011                 if (!dirent->inode)
8012                         goto next;
8013
8014                 /*
8015                  * Make sure the inode listed is a legal one.
8016                  */
8017                 if (((dirent->inode != EXT2_ROOT_INO) &&
8018                      (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
8019                     (dirent->inode > fs->super->s_inodes_count)) {
8020                         problem = PR_2_BAD_INO;
8021                 } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
8022                                                dirent->inode))) {
8023                         /*
8024                          * If the inode is unused, offer to clear it.
8025                          */
8026                         problem = PR_2_UNUSED_INODE;
8027                 } else if (ctx->inode_bb_map &&
8028                            (ext2fs_test_inode_bitmap(ctx->inode_bb_map,
8029                                                      dirent->inode))) {
8030                         /*
8031                          * If the inode is in a bad block, offer to
8032                          * clear it.
8033                          */
8034                         problem = PR_2_BB_INODE;
8035                 } else if ((dot_state > 1) &&
8036                            ((dirent->name_len & 0xFF) == 1) &&
8037                            (dirent->name[0] == '.')) {
8038                         /*
8039                          * If there's a '.' entry in anything other
8040                          * than the first directory entry, it's a
8041                          * duplicate entry that should be removed.
8042                          */
8043                         problem = PR_2_DUP_DOT;
8044                 } else if ((dot_state > 1) &&
8045                            ((dirent->name_len & 0xFF) == 2) &&
8046                            (dirent->name[0] == '.') &&
8047                            (dirent->name[1] == '.')) {
8048                         /*
8049                          * If there's a '..' entry in anything other
8050                          * than the second directory entry, it's a
8051                          * duplicate entry that should be removed.
8052                          */
8053                         problem = PR_2_DUP_DOT_DOT;
8054                 } else if ((dot_state > 1) &&
8055                            (dirent->inode == EXT2_ROOT_INO)) {
8056                         /*
8057                          * Don't allow links to the root directory.
8058                          * We check this specially to make sure we
8059                          * catch this error case even if the root
8060                          * directory hasn't been created yet.
8061                          */
8062                         problem = PR_2_LINK_ROOT;
8063                 } else if ((dot_state > 1) &&
8064                            (dirent->name_len & 0xFF) == 0) {
8065                         /*
8066                          * Don't allow zero-length directory names.
8067                          */
8068                         problem = PR_2_NULL_NAME;
8069                 }
8070
8071                 if (problem) {
8072                         if (fix_problem(ctx, problem, &cd->pctx)) {
8073                                 dirent->inode = 0;
8074                                 dir_modified++;
8075                                 goto next;
8076                         } else {
8077                                 ext2fs_unmark_valid(fs);
8078                                 if (problem == PR_2_BAD_INO)
8079                                         goto next;
8080                         }
8081                 }
8082
8083                 /*
8084                  * If the inode was marked as having bad fields in
8085                  * pass1, process it and offer to fix/clear it.
8086                  * (We wait until now so that we can display the
8087                  * pathname to the user.)
8088                  */
8089                 if (ctx->inode_bad_map &&
8090                     ext2fs_test_inode_bitmap(ctx->inode_bad_map,
8091                                              dirent->inode)) {
8092                         if (e2fsck_process_bad_inode(ctx, ino,
8093                                                      dirent->inode,
8094                                                      buf + fs->blocksize)) {
8095                                 dirent->inode = 0;
8096                                 dir_modified++;
8097                                 goto next;
8098                         }
8099                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8100                                 return DIRENT_ABORT;
8101                 }
8102
8103                 if (check_name(ctx, dirent, &cd->pctx))
8104                         dir_modified++;
8105
8106                 if (check_filetype(ctx, dirent, &cd->pctx))
8107                         dir_modified++;
8108
8109 #ifdef ENABLE_HTREE
8110                 if (dx_db) {
8111                         ext2fs_dirhash(dx_dir->hashversion, dirent->name,
8112                                        (dirent->name_len & 0xFF),
8113                                        fs->super->s_hash_seed, &hash, 0);
8114                         if (hash < dx_db->min_hash)
8115                                 dx_db->min_hash = hash;
8116                         if (hash > dx_db->max_hash)
8117                                 dx_db->max_hash = hash;
8118                 }
8119 #endif
8120
8121                 /*
8122                  * If this is a directory, then mark its parent in its
8123                  * dir_info structure.  If the parent field is already
8124                  * filled in, then this directory has more than one
8125                  * hard link.  We assume the first link is correct,
8126                  * and ask the user if he/she wants to clear this one.
8127                  */
8128                 if ((dot_state > 1) &&
8129                     (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
8130                                               dirent->inode))) {
8131                         subdir = e2fsck_get_dir_info(ctx, dirent->inode);
8132                         if (!subdir) {
8133                                 cd->pctx.ino = dirent->inode;
8134                                 fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
8135                                 goto abort_free_dict;
8136                         }
8137                         if (subdir->parent) {
8138                                 cd->pctx.ino2 = subdir->parent;
8139                                 if (fix_problem(ctx, PR_2_LINK_DIR,
8140                                                 &cd->pctx)) {
8141                                         dirent->inode = 0;
8142                                         dir_modified++;
8143                                         goto next;
8144                                 }
8145                                 cd->pctx.ino2 = 0;
8146                         } else
8147                                 subdir->parent = ino;
8148                 }
8149
8150                 if (dups_found) {
8151                         ;
8152                 } else if (dict_lookup(&de_dict, dirent)) {
8153                         clear_problem_context(&pctx);
8154                         pctx.ino = ino;
8155                         pctx.dirent = dirent;
8156                         fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
8157                         if (!ctx->dirs_to_hash)
8158                                 ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
8159                         if (ctx->dirs_to_hash)
8160                                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
8161                         dups_found++;
8162                 } else
8163                         dict_alloc_insert(&de_dict, dirent, dirent);
8164
8165                 ext2fs_icount_increment(ctx->inode_count, dirent->inode,
8166                                         &links);
8167                 if (links > 1)
8168                         ctx->fs_links_count++;
8169                 ctx->fs_total_count++;
8170         next:
8171                 prev = dirent;
8172                 offset += dirent->rec_len;
8173                 dot_state++;
8174         } while (offset < fs->blocksize);
8175 #if 0
8176         printf("\n");
8177 #endif
8178 #ifdef ENABLE_HTREE
8179         if (dx_db) {
8180 #ifdef DX_DEBUG
8181                 printf("db_block %d, type %d, min_hash 0x%0x, max_hash 0x%0x\n",
8182                        db->blockcnt, dx_db->type,
8183                        dx_db->min_hash, dx_db->max_hash);
8184 #endif
8185                 cd->pctx.dir = cd->pctx.ino;
8186                 if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
8187                     (dx_db->type == DX_DIRBLOCK_NODE))
8188                         parse_int_node(fs, db, cd, dx_dir, buf);
8189         }
8190 #endif /* ENABLE_HTREE */
8191         if (offset != fs->blocksize) {
8192                 cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
8193                 if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
8194                         dirent->rec_len = cd->pctx.num;
8195                         dir_modified++;
8196                 }
8197         }
8198         if (dir_modified) {
8199                 cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
8200                 if (cd->pctx.errcode) {
8201                         if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
8202                                          &cd->pctx))
8203                                 goto abort_free_dict;
8204                 }
8205                 ext2fs_mark_changed(fs);
8206         }
8207         dict_free_nodes(&de_dict);
8208         return 0;
8209 abort_free_dict:
8210         dict_free_nodes(&de_dict);
8211         ctx->flags |= E2F_FLAG_ABORT;
8212         return DIRENT_ABORT;
8213 }
8214
8215 /*
8216  * This function is called to deallocate a block, and is an interator
8217  * functioned called by deallocate inode via ext2fs_iterate_block().
8218  */
8219 static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
8220                                   e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
8221                                   blk_t ref_block FSCK_ATTR((unused)),
8222                                   int ref_offset FSCK_ATTR((unused)),
8223                                   void *priv_data)
8224 {
8225         e2fsck_t        ctx = (e2fsck_t) priv_data;
8226
8227         if (HOLE_BLKADDR(*block_nr))
8228                 return 0;
8229         if ((*block_nr < fs->super->s_first_data_block) ||
8230             (*block_nr >= fs->super->s_blocks_count))
8231                 return 0;
8232         ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
8233         ext2fs_block_alloc_stats(fs, *block_nr, -1);
8234         return 0;
8235 }
8236
8237 /*
8238  * This fuction deallocates an inode
8239  */
8240 static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
8241 {
8242         ext2_filsys fs = ctx->fs;
8243         struct ext2_inode       inode;
8244         struct problem_context  pctx;
8245         __u32                   count;
8246
8247         ext2fs_icount_store(ctx->inode_link_info, ino, 0);
8248         e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
8249         inode.i_links_count = 0;
8250         inode.i_dtime = time(0);
8251         e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
8252         clear_problem_context(&pctx);
8253         pctx.ino = ino;
8254
8255         /*
8256          * Fix up the bitmaps...
8257          */
8258         e2fsck_read_bitmaps(ctx);
8259         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
8260         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
8261         if (ctx->inode_bad_map)
8262                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
8263         ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
8264
8265         if (inode.i_file_acl &&
8266             (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
8267                 pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
8268                                                    block_buf, -1, &count);
8269                 if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
8270                         pctx.errcode = 0;
8271                         count = 1;
8272                 }
8273                 if (pctx.errcode) {
8274                         pctx.blk = inode.i_file_acl;
8275                         fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
8276                         ctx->flags |= E2F_FLAG_ABORT;
8277                         return;
8278                 }
8279                 if (count == 0) {
8280                         ext2fs_unmark_block_bitmap(ctx->block_found_map,
8281                                                    inode.i_file_acl);
8282                         ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
8283                 }
8284                 inode.i_file_acl = 0;
8285         }
8286
8287         if (!ext2fs_inode_has_valid_blocks(&inode))
8288                 return;
8289
8290         if (LINUX_S_ISREG(inode.i_mode) &&
8291             (inode.i_size_high || inode.i_size & 0x80000000UL))
8292                 ctx->large_files--;
8293
8294         pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
8295                                             deallocate_inode_block, ctx);
8296         if (pctx.errcode) {
8297                 fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
8298                 ctx->flags |= E2F_FLAG_ABORT;
8299                 return;
8300         }
8301 }
8302
8303 /*
8304  * This fuction clears the htree flag on an inode
8305  */
8306 static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
8307 {
8308         struct ext2_inode       inode;
8309
8310         e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
8311         inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
8312         e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
8313         if (ctx->dirs_to_hash)
8314                 ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
8315 }
8316
8317
8318 static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
8319                                     ext2_ino_t ino, char *buf)
8320 {
8321         ext2_filsys fs = ctx->fs;
8322         struct ext2_inode       inode;
8323         int                     inode_modified = 0;
8324         int                     not_fixed = 0;
8325         unsigned char           *frag, *fsize;
8326         struct problem_context  pctx;
8327         int     problem = 0;
8328
8329         e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
8330
8331         clear_problem_context(&pctx);
8332         pctx.ino = ino;
8333         pctx.dir = dir;
8334         pctx.inode = &inode;
8335
8336         if (inode.i_file_acl &&
8337             !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
8338             fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
8339                 inode.i_file_acl = 0;
8340 #ifdef EXT2FS_ENABLE_SWAPFS
8341                 /*
8342                  * This is a special kludge to deal with long symlinks
8343                  * on big endian systems.  i_blocks had already been
8344                  * decremented earlier in pass 1, but since i_file_acl
8345                  * hadn't yet been cleared, ext2fs_read_inode()
8346                  * assumed that the file was short symlink and would
8347                  * not have byte swapped i_block[0].  Hence, we have
8348                  * to byte-swap it here.
8349                  */
8350                 if (LINUX_S_ISLNK(inode.i_mode) &&
8351                     (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
8352                     (inode.i_blocks == fs->blocksize >> 9))
8353                         inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
8354 #endif
8355                 inode_modified++;
8356         } else
8357                 not_fixed++;
8358
8359         if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
8360             !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
8361             !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
8362             !(LINUX_S_ISSOCK(inode.i_mode)))
8363                 problem = PR_2_BAD_MODE;
8364         else if (LINUX_S_ISCHR(inode.i_mode)
8365                  && !e2fsck_pass1_check_device_inode(fs, &inode))
8366                 problem = PR_2_BAD_CHAR_DEV;
8367         else if (LINUX_S_ISBLK(inode.i_mode)
8368                  && !e2fsck_pass1_check_device_inode(fs, &inode))
8369                 problem = PR_2_BAD_BLOCK_DEV;
8370         else if (LINUX_S_ISFIFO(inode.i_mode)
8371                  && !e2fsck_pass1_check_device_inode(fs, &inode))
8372                 problem = PR_2_BAD_FIFO;
8373         else if (LINUX_S_ISSOCK(inode.i_mode)
8374                  && !e2fsck_pass1_check_device_inode(fs, &inode))
8375                 problem = PR_2_BAD_SOCKET;
8376         else if (LINUX_S_ISLNK(inode.i_mode)
8377                  && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
8378                 problem = PR_2_INVALID_SYMLINK;
8379         }
8380
8381         if (problem) {
8382                 if (fix_problem(ctx, problem, &pctx)) {
8383                         deallocate_inode(ctx, ino, 0);
8384                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8385                                 return 0;
8386                         return 1;
8387                 } else
8388                         not_fixed++;
8389                 problem = 0;
8390         }
8391
8392         if (inode.i_faddr) {
8393                 if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
8394                         inode.i_faddr = 0;
8395                         inode_modified++;
8396                 } else
8397                         not_fixed++;
8398         }
8399
8400         switch (fs->super->s_creator_os) {
8401             case EXT2_OS_LINUX:
8402                 frag = &inode.osd2.linux2.l_i_frag;
8403                 fsize = &inode.osd2.linux2.l_i_fsize;
8404                 break;
8405             case EXT2_OS_HURD:
8406                 frag = &inode.osd2.hurd2.h_i_frag;
8407                 fsize = &inode.osd2.hurd2.h_i_fsize;
8408                 break;
8409             case EXT2_OS_MASIX:
8410                 frag = &inode.osd2.masix2.m_i_frag;
8411                 fsize = &inode.osd2.masix2.m_i_fsize;
8412                 break;
8413             default:
8414                 frag = fsize = 0;
8415         }
8416         if (frag && *frag) {
8417                 pctx.num = *frag;
8418                 if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
8419                         *frag = 0;
8420                         inode_modified++;
8421                 } else
8422                         not_fixed++;
8423                 pctx.num = 0;
8424         }
8425         if (fsize && *fsize) {
8426                 pctx.num = *fsize;
8427                 if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
8428                         *fsize = 0;
8429                         inode_modified++;
8430                 } else
8431                         not_fixed++;
8432                 pctx.num = 0;
8433         }
8434
8435         if (inode.i_file_acl &&
8436             ((inode.i_file_acl < fs->super->s_first_data_block) ||
8437              (inode.i_file_acl >= fs->super->s_blocks_count))) {
8438                 if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
8439                         inode.i_file_acl = 0;
8440                         inode_modified++;
8441                 } else
8442                         not_fixed++;
8443         }
8444         if (inode.i_dir_acl &&
8445             LINUX_S_ISDIR(inode.i_mode)) {
8446                 if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
8447                         inode.i_dir_acl = 0;
8448                         inode_modified++;
8449                 } else
8450                         not_fixed++;
8451         }
8452
8453         if (inode_modified)
8454                 e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
8455         if (!not_fixed)
8456                 ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
8457         return 0;
8458 }
8459
8460
8461 /*
8462  * allocate_dir_block --- this function allocates a new directory
8463  *      block for a particular inode; this is done if a directory has
8464  *      a "hole" in it, or if a directory has a illegal block number
8465  *      that was zeroed out and now needs to be replaced.
8466  */
8467 static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
8468                               struct problem_context *pctx)
8469 {
8470         ext2_filsys fs = ctx->fs;
8471         blk_t                   blk;
8472         char                    *block;
8473         struct ext2_inode       inode;
8474
8475         if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
8476                 return 1;
8477
8478         /*
8479          * Read the inode and block bitmaps in; we'll be messing with
8480          * them.
8481          */
8482         e2fsck_read_bitmaps(ctx);
8483
8484         /*
8485          * First, find a free block
8486          */
8487         pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8488         if (pctx->errcode) {
8489                 pctx->str = "ext2fs_new_block";
8490                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8491                 return 1;
8492         }
8493         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8494         ext2fs_mark_block_bitmap(fs->block_map, blk);
8495         ext2fs_mark_bb_dirty(fs);
8496
8497         /*
8498          * Now let's create the actual data block for the inode
8499          */
8500         if (db->blockcnt)
8501                 pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
8502         else
8503                 pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
8504                                                      EXT2_ROOT_INO, &block);
8505
8506         if (pctx->errcode) {
8507                 pctx->str = "ext2fs_new_dir_block";
8508                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8509                 return 1;
8510         }
8511
8512         pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
8513         ext2fs_free_mem(&block);
8514         if (pctx->errcode) {
8515                 pctx->str = "ext2fs_write_dir_block";
8516                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8517                 return 1;
8518         }
8519
8520         /*
8521          * Update the inode block count
8522          */
8523         e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
8524         inode.i_blocks += fs->blocksize / 512;
8525         if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
8526                 inode.i_size = (db->blockcnt+1) * fs->blocksize;
8527         e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
8528
8529         /*
8530          * Finally, update the block pointers for the inode
8531          */
8532         db->blk = blk;
8533         pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
8534                                       0, update_dir_block, db);
8535         if (pctx->errcode) {
8536                 pctx->str = "ext2fs_block_iterate";
8537                 fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
8538                 return 1;
8539         }
8540
8541         return 0;
8542 }
8543
8544 /*
8545  * This is a helper function for allocate_dir_block().
8546  */
8547 static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
8548                             blk_t       *block_nr,
8549                             e2_blkcnt_t blockcnt,
8550                             blk_t ref_block FSCK_ATTR((unused)),
8551                             int ref_offset FSCK_ATTR((unused)),
8552                             void *priv_data)
8553 {
8554         struct ext2_db_entry *db;
8555
8556         db = (struct ext2_db_entry *) priv_data;
8557         if (db->blockcnt == (int) blockcnt) {
8558                 *block_nr = db->blk;
8559                 return BLOCK_CHANGED;
8560         }
8561         return 0;
8562 }
8563
8564 /*
8565  * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
8566  *
8567  * Pass #3 assures that all directories are connected to the
8568  * filesystem tree, using the following algorithm:
8569  *
8570  * First, the root directory is checked to make sure it exists; if
8571  * not, e2fsck will offer to create a new one.  It is then marked as
8572  * "done".
8573  *
8574  * Then, pass3 interates over all directory inodes; for each directory
8575  * it attempts to trace up the filesystem tree, using dirinfo.parent
8576  * until it reaches a directory which has been marked "done".  If it
8577  * can not do so, then the directory must be disconnected, and e2fsck
8578  * will offer to reconnect it to /lost+found.  While it is chasing
8579  * parent pointers up the filesystem tree, if pass3 sees a directory
8580  * twice, then it has detected a filesystem loop, and it will again
8581  * offer to reconnect the directory to /lost+found in to break the
8582  * filesystem loop.
8583  *
8584  * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
8585  * reconnect inodes to /lost+found; this subroutine is also used by
8586  * pass 4.  e2fsck_reconnect_file() calls get_lost_and_found(), which
8587  * is responsible for creating /lost+found if it does not exist.
8588  *
8589  * Pass 3 frees the following data structures:
8590  *      - The dirinfo directory information cache.
8591  */
8592
8593 static void check_root(e2fsck_t ctx);
8594 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
8595                            struct problem_context *pctx);
8596 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
8597
8598 static ext2fs_inode_bitmap inode_loop_detect;
8599 static ext2fs_inode_bitmap inode_done_map;
8600
8601 static void e2fsck_pass3(e2fsck_t ctx)
8602 {
8603         ext2_filsys fs = ctx->fs;
8604         int             i;
8605 #ifdef RESOURCE_TRACK
8606         struct resource_track   rtrack;
8607 #endif
8608         struct problem_context  pctx;
8609         struct dir_info *dir;
8610         unsigned long maxdirs, count;
8611
8612 #ifdef RESOURCE_TRACK
8613         init_resource_track(&rtrack);
8614 #endif
8615
8616         clear_problem_context(&pctx);
8617
8618 #ifdef MTRACE
8619         mtrace_print("Pass 3");
8620 #endif
8621
8622         if (!(ctx->options & E2F_OPT_PREEN))
8623                 fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
8624
8625         /*
8626          * Allocate some bitmaps to do loop detection.
8627          */
8628         pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
8629                                                     &inode_done_map);
8630         if (pctx.errcode) {
8631                 pctx.num = 2;
8632                 fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
8633                 ctx->flags |= E2F_FLAG_ABORT;
8634                 goto abort_exit;
8635         }
8636 #ifdef RESOURCE_TRACK
8637         if (ctx->options & E2F_OPT_TIME) {
8638                 e2fsck_clear_progbar(ctx);
8639                 print_resource_track(_("Peak memory"), &ctx->global_rtrack);
8640         }
8641 #endif
8642
8643         check_root(ctx);
8644         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8645                 goto abort_exit;
8646
8647         ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
8648
8649         maxdirs = e2fsck_get_num_dirinfo(ctx);
8650         count = 1;
8651
8652         if (ctx->progress)
8653                 if ((ctx->progress)(ctx, 3, 0, maxdirs))
8654                         goto abort_exit;
8655
8656         for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
8657                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8658                         goto abort_exit;
8659                 if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
8660                         goto abort_exit;
8661                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
8662                         if (check_directory(ctx, dir, &pctx))
8663                                 goto abort_exit;
8664         }
8665
8666         /*
8667          * Force the creation of /lost+found if not present
8668          */
8669         if ((ctx->flags & E2F_OPT_READONLY) == 0)
8670                 e2fsck_get_lost_and_found(ctx, 1);
8671
8672         /*
8673          * If there are any directories that need to be indexed or
8674          * optimized, do it here.
8675          */
8676         e2fsck_rehash_directories(ctx);
8677
8678 abort_exit:
8679         e2fsck_free_dir_info(ctx);
8680         if (inode_loop_detect) {
8681                 ext2fs_free_inode_bitmap(inode_loop_detect);
8682                 inode_loop_detect = 0;
8683         }
8684         if (inode_done_map) {
8685                 ext2fs_free_inode_bitmap(inode_done_map);
8686                 inode_done_map = 0;
8687         }
8688
8689 #ifdef RESOURCE_TRACK
8690         if (ctx->options & E2F_OPT_TIME2) {
8691                 e2fsck_clear_progbar(ctx);
8692                 print_resource_track(_("Pass 3"), &rtrack);
8693         }
8694 #endif
8695 }
8696
8697 /*
8698  * This makes sure the root inode is present; if not, we ask if the
8699  * user wants us to create it.  Not creating it is a fatal error.
8700  */
8701 static void check_root(e2fsck_t ctx)
8702 {
8703         ext2_filsys fs = ctx->fs;
8704         blk_t                   blk;
8705         struct ext2_inode       inode;
8706         char *                  block;
8707         struct problem_context  pctx;
8708
8709         clear_problem_context(&pctx);
8710
8711         if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
8712                 /*
8713                  * If the root inode is not a directory, die here.  The
8714                  * user must have answered 'no' in pass1 when we
8715                  * offered to clear it.
8716                  */
8717                 if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
8718                                                EXT2_ROOT_INO))) {
8719                         fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
8720                         ctx->flags |= E2F_FLAG_ABORT;
8721                 }
8722                 return;
8723         }
8724
8725         if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
8726                 fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
8727                 ctx->flags |= E2F_FLAG_ABORT;
8728                 return;
8729         }
8730
8731         e2fsck_read_bitmaps(ctx);
8732
8733         /*
8734          * First, find a free block
8735          */
8736         pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8737         if (pctx.errcode) {
8738                 pctx.str = "ext2fs_new_block";
8739                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8740                 ctx->flags |= E2F_FLAG_ABORT;
8741                 return;
8742         }
8743         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8744         ext2fs_mark_block_bitmap(fs->block_map, blk);
8745         ext2fs_mark_bb_dirty(fs);
8746
8747         /*
8748          * Now let's create the actual data block for the inode
8749          */
8750         pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
8751                                             &block);
8752         if (pctx.errcode) {
8753                 pctx.str = "ext2fs_new_dir_block";
8754                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8755                 ctx->flags |= E2F_FLAG_ABORT;
8756                 return;
8757         }
8758
8759         pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
8760         if (pctx.errcode) {
8761                 pctx.str = "ext2fs_write_dir_block";
8762                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8763                 ctx->flags |= E2F_FLAG_ABORT;
8764                 return;
8765         }
8766         ext2fs_free_mem(&block);
8767
8768         /*
8769          * Set up the inode structure
8770          */
8771         memset(&inode, 0, sizeof(inode));
8772         inode.i_mode = 040755;
8773         inode.i_size = fs->blocksize;
8774         inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
8775         inode.i_links_count = 2;
8776         inode.i_blocks = fs->blocksize / 512;
8777         inode.i_block[0] = blk;
8778
8779         /*
8780          * Write out the inode.
8781          */
8782         pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
8783         if (pctx.errcode) {
8784                 pctx.str = "ext2fs_write_inode";
8785                 fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
8786                 ctx->flags |= E2F_FLAG_ABORT;
8787                 return;
8788         }
8789
8790         /*
8791          * Miscellaneous bookkeeping...
8792          */
8793         e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
8794         ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
8795         ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
8796
8797         ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
8798         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
8799         ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
8800         ext2fs_mark_ib_dirty(fs);
8801 }
8802
8803 /*
8804  * This subroutine is responsible for making sure that a particular
8805  * directory is connected to the root; if it isn't we trace it up as
8806  * far as we can go, and then offer to connect the resulting parent to
8807  * the lost+found.  We have to do loop detection; if we ever discover
8808  * a loop, we treat that as a disconnected directory and offer to
8809  * reparent it to lost+found.
8810  *
8811  * However, loop detection is expensive, because for very large
8812  * filesystems, the inode_loop_detect bitmap is huge, and clearing it
8813  * is non-trivial.  Loops in filesystems are also a rare error case,
8814  * and we shouldn't optimize for error cases.  So we try two passes of
8815  * the algorithm.  The first time, we ignore loop detection and merely
8816  * increment a counter; if the counter exceeds some extreme threshold,
8817  * then we try again with the loop detection bitmap enabled.
8818  */
8819 static int check_directory(e2fsck_t ctx, struct dir_info *dir,
8820                            struct problem_context *pctx)
8821 {
8822         ext2_filsys     fs = ctx->fs;
8823         struct dir_info *p = dir;
8824         int             loop_pass = 0, parent_count = 0;
8825
8826         if (!p)
8827                 return 0;
8828
8829         while (1) {
8830                 /*
8831                  * Mark this inode as being "done"; by the time we
8832                  * return from this function, the inode we either be
8833                  * verified as being connected to the directory tree,
8834                  * or we will have offered to reconnect this to
8835                  * lost+found.
8836                  *
8837                  * If it was marked done already, then we've reached a
8838                  * parent we've already checked.
8839                  */
8840                 if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
8841                         break;
8842
8843                 /*
8844                  * If this directory doesn't have a parent, or we've
8845                  * seen the parent once already, then offer to
8846                  * reparent it to lost+found
8847                  */
8848                 if (!p->parent ||
8849                     (loop_pass &&
8850                      (ext2fs_test_inode_bitmap(inode_loop_detect,
8851                                               p->parent)))) {
8852                         pctx->ino = p->ino;
8853                         if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
8854                                 if (e2fsck_reconnect_file(ctx, pctx->ino))
8855                                         ext2fs_unmark_valid(fs);
8856                                 else {
8857                                         p = e2fsck_get_dir_info(ctx, pctx->ino);
8858                                         p->parent = ctx->lost_and_found;
8859                                         fix_dotdot(ctx, p, ctx->lost_and_found);
8860                                 }
8861                         }
8862                         break;
8863                 }
8864                 p = e2fsck_get_dir_info(ctx, p->parent);
8865                 if (!p) {
8866                         fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
8867                         return 0;
8868                 }
8869                 if (loop_pass) {
8870                         ext2fs_mark_inode_bitmap(inode_loop_detect,
8871                                                  p->ino);
8872                 } else if (parent_count++ > 2048) {
8873                         /*
8874                          * If we've run into a path depth that's
8875                          * greater than 2048, try again with the inode
8876                          * loop bitmap turned on and start from the
8877                          * top.
8878                          */
8879                         loop_pass = 1;
8880                         if (inode_loop_detect)
8881                                 ext2fs_clear_inode_bitmap(inode_loop_detect);
8882                         else {
8883                                 pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
8884                                 if (pctx->errcode) {
8885                                         pctx->num = 1;
8886                                         fix_problem(ctx,
8887                                     PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
8888                                         ctx->flags |= E2F_FLAG_ABORT;
8889                                         return -1;
8890                                 }
8891                         }
8892                         p = dir;
8893                 }
8894         }
8895
8896         /*
8897          * Make sure that .. and the parent directory are the same;
8898          * offer to fix it if not.
8899          */
8900         if (dir->parent != dir->dotdot) {
8901                 pctx->ino = dir->ino;
8902                 pctx->ino2 = dir->dotdot;
8903                 pctx->dir = dir->parent;
8904                 if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
8905                         fix_dotdot(ctx, dir, dir->parent);
8906         }
8907         return 0;
8908 }
8909
8910 /*
8911  * This routine gets the lost_and_found inode, making it a directory
8912  * if necessary
8913  */
8914 ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
8915 {
8916         ext2_filsys fs = ctx->fs;
8917         ext2_ino_t                      ino;
8918         blk_t                   blk;
8919         errcode_t               retval;
8920         struct ext2_inode       inode;
8921         char *                  block;
8922         static const char       name[] = "lost+found";
8923         struct  problem_context pctx;
8924         struct dir_info         *dirinfo;
8925
8926         if (ctx->lost_and_found)
8927                 return ctx->lost_and_found;
8928
8929         clear_problem_context(&pctx);
8930
8931         retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
8932                                sizeof(name)-1, 0, &ino);
8933         if (retval && !fix)
8934                 return 0;
8935         if (!retval) {
8936                 if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
8937                         ctx->lost_and_found = ino;
8938                         return ino;
8939                 }
8940
8941                 /* Lost+found isn't a directory! */
8942                 if (!fix)
8943                         return 0;
8944                 pctx.ino = ino;
8945                 if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
8946                         return 0;
8947
8948                 /* OK, unlink the old /lost+found file. */
8949                 pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
8950                 if (pctx.errcode) {
8951                         pctx.str = "ext2fs_unlink";
8952                         fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
8953                         return 0;
8954                 }
8955                 dirinfo = e2fsck_get_dir_info(ctx, ino);
8956                 if (dirinfo)
8957                         dirinfo->parent = 0;
8958                 e2fsck_adjust_inode_count(ctx, ino, -1);
8959         } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
8960                 pctx.errcode = retval;
8961                 fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
8962         }
8963         if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
8964                 return 0;
8965
8966         /*
8967          * Read the inode and block bitmaps in; we'll be messing with
8968          * them.
8969          */
8970         e2fsck_read_bitmaps(ctx);
8971
8972         /*
8973          * First, find a free block
8974          */
8975         retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
8976         if (retval) {
8977                 pctx.errcode = retval;
8978                 fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
8979                 return 0;
8980         }
8981         ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
8982         ext2fs_block_alloc_stats(fs, blk, +1);
8983
8984         /*
8985          * Next find a free inode.
8986          */
8987         retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
8988                                   ctx->inode_used_map, &ino);
8989         if (retval) {
8990                 pctx.errcode = retval;
8991                 fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
8992                 return 0;
8993         }
8994         ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
8995         ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
8996         ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
8997
8998         /*
8999          * Now let's create the actual data block for the inode
9000          */
9001         retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
9002         if (retval) {
9003                 pctx.errcode = retval;
9004                 fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
9005                 return 0;
9006         }
9007
9008         retval = ext2fs_write_dir_block(fs, blk, block);
9009         ext2fs_free_mem(&block);
9010         if (retval) {
9011                 pctx.errcode = retval;
9012                 fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
9013                 return 0;
9014         }
9015
9016         /*
9017          * Set up the inode structure
9018          */
9019         memset(&inode, 0, sizeof(inode));
9020         inode.i_mode = 040700;
9021         inode.i_size = fs->blocksize;
9022         inode.i_atime = inode.i_ctime = inode.i_mtime = time(0);
9023         inode.i_links_count = 2;
9024         inode.i_blocks = fs->blocksize / 512;
9025         inode.i_block[0] = blk;
9026
9027         /*
9028          * Next, write out the inode.
9029          */
9030         pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
9031         if (pctx.errcode) {
9032                 pctx.str = "ext2fs_write_inode";
9033                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
9034                 return 0;
9035         }
9036         /*
9037          * Finally, create the directory link
9038          */
9039         pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
9040         if (pctx.errcode) {
9041                 pctx.str = "ext2fs_link";
9042                 fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
9043                 return 0;
9044         }
9045
9046         /*
9047          * Miscellaneous bookkeeping that needs to be kept straight.
9048          */
9049         e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
9050         e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
9051         ext2fs_icount_store(ctx->inode_count, ino, 2);
9052         ext2fs_icount_store(ctx->inode_link_info, ino, 2);
9053         ctx->lost_and_found = ino;
9054 #if 0
9055         printf("/lost+found created; inode #%lu\n", ino);
9056 #endif
9057         return ino;
9058 }
9059
9060 /*
9061  * This routine will connect a file to lost+found
9062  */
9063 int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
9064 {
9065         ext2_filsys fs = ctx->fs;
9066         errcode_t       retval;
9067         char            name[80];
9068         struct problem_context  pctx;
9069         struct ext2_inode       inode;
9070         int             file_type = 0;
9071
9072         clear_problem_context(&pctx);
9073         pctx.ino = ino;
9074
9075         if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
9076                 if (e2fsck_get_lost_and_found(ctx, 1) == 0)
9077                         ctx->bad_lost_and_found++;
9078         }
9079         if (ctx->bad_lost_and_found) {
9080                 fix_problem(ctx, PR_3_NO_LPF, &pctx);
9081                 return 1;
9082         }
9083
9084         sprintf(name, "#%u", ino);
9085         if (ext2fs_read_inode(fs, ino, &inode) == 0)
9086                 file_type = ext2_file_type(inode.i_mode);
9087         retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
9088         if (retval == EXT2_ET_DIR_NO_SPACE) {
9089                 if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
9090                         return 1;
9091                 retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
9092                                                  1, 0);
9093                 if (retval) {
9094                         pctx.errcode = retval;
9095                         fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
9096                         return 1;
9097                 }
9098                 retval = ext2fs_link(fs, ctx->lost_and_found, name,
9099                                      ino, file_type);
9100         }
9101         if (retval) {
9102                 pctx.errcode = retval;
9103                 fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
9104                 return 1;
9105         }
9106         e2fsck_adjust_inode_count(ctx, ino, 1);
9107
9108         return 0;
9109 }
9110
9111 /*
9112  * Utility routine to adjust the inode counts on an inode.
9113  */
9114 errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
9115 {
9116         ext2_filsys fs = ctx->fs;
9117         errcode_t               retval;
9118         struct ext2_inode       inode;
9119
9120         if (!ino)
9121                 return 0;
9122
9123         retval = ext2fs_read_inode(fs, ino, &inode);
9124         if (retval)
9125                 return retval;
9126
9127 #if 0
9128         printf("Adjusting link count for inode %lu by %d (from %d)\n", ino, adj,
9129                inode.i_links_count);
9130 #endif
9131
9132         if (adj == 1) {
9133                 ext2fs_icount_increment(ctx->inode_count, ino, 0);
9134                 if (inode.i_links_count == (__u16) ~0)
9135                         return 0;
9136                 ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
9137                 inode.i_links_count++;
9138         } else if (adj == -1) {
9139                 ext2fs_icount_decrement(ctx->inode_count, ino, 0);
9140                 if (inode.i_links_count == 0)
9141                         return 0;
9142                 ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
9143                 inode.i_links_count--;
9144         }
9145
9146         retval = ext2fs_write_inode(fs, ino, &inode);
9147         if (retval)
9148                 return retval;
9149
9150         return 0;
9151 }
9152
9153 /*
9154  * Fix parent --- this routine fixes up the parent of a directory.
9155  */
9156 struct fix_dotdot_struct {
9157         ext2_filsys     fs;
9158         ext2_ino_t      parent;
9159         int             done;
9160         e2fsck_t        ctx;
9161 };
9162
9163 static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
9164                            int  offset FSCK_ATTR((unused)),
9165                            int  blocksize FSCK_ATTR((unused)),
9166                            char *buf FSCK_ATTR((unused)),
9167                            void *priv_data)
9168 {
9169         struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
9170         errcode_t       retval;
9171         struct problem_context pctx;
9172
9173         if ((dirent->name_len & 0xFF) != 2)
9174                 return 0;
9175         if (strncmp(dirent->name, "..", 2))
9176                 return 0;
9177
9178         clear_problem_context(&pctx);
9179
9180         retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
9181         if (retval) {
9182                 pctx.errcode = retval;
9183                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
9184         }
9185         retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
9186         if (retval) {
9187                 pctx.errcode = retval;
9188                 fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
9189         }
9190         dirent->inode = fp->parent;
9191
9192         fp->done++;
9193         return DIRENT_ABORT | DIRENT_CHANGED;
9194 }
9195
9196 static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
9197 {
9198         ext2_filsys fs = ctx->fs;
9199         errcode_t       retval;
9200         struct fix_dotdot_struct fp;
9201         struct problem_context pctx;
9202
9203         fp.fs = fs;
9204         fp.parent = parent;
9205         fp.done = 0;
9206         fp.ctx = ctx;
9207
9208 #if 0
9209         printf("Fixing '..' of inode %lu to be %lu...\n", dir->ino, parent);
9210 #endif
9211
9212         retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
9213                                     0, fix_dotdot_proc, &fp);
9214         if (retval || !fp.done) {
9215                 clear_problem_context(&pctx);
9216                 pctx.ino = dir->ino;
9217                 pctx.errcode = retval;
9218                 fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
9219                             PR_3_FIX_PARENT_NOFIND, &pctx);
9220                 ext2fs_unmark_valid(fs);
9221         }
9222         dir->dotdot = parent;
9223
9224         return;
9225 }
9226
9227 /*
9228  * These routines are responsible for expanding a /lost+found if it is
9229  * too small.
9230  */
9231
9232 struct expand_dir_struct {
9233         int                     num;
9234         int                     guaranteed_size;
9235         int                     newblocks;
9236         int                     last_block;
9237         errcode_t               err;
9238         e2fsck_t                ctx;
9239 };
9240
9241 static int expand_dir_proc(ext2_filsys fs,
9242                            blk_t        *blocknr,
9243                            e2_blkcnt_t  blockcnt,
9244                            blk_t ref_block FSCK_ATTR((unused)),
9245                            int ref_offset FSCK_ATTR((unused)),
9246                            void *priv_data)
9247 {
9248         struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
9249         blk_t   new_blk;
9250         static blk_t    last_blk = 0;
9251         char            *block;
9252         errcode_t       retval;
9253         e2fsck_t        ctx;
9254
9255         ctx = es->ctx;
9256
9257         if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
9258                 return BLOCK_ABORT;
9259
9260         if (blockcnt > 0)
9261                 es->last_block = blockcnt;
9262         if (*blocknr) {
9263                 last_blk = *blocknr;
9264                 return 0;
9265         }
9266         retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
9267                                   &new_blk);
9268         if (retval) {
9269                 es->err = retval;
9270                 return BLOCK_ABORT;
9271         }
9272         if (blockcnt > 0) {
9273                 retval = ext2fs_new_dir_block(fs, 0, 0, &block);
9274                 if (retval) {
9275                         es->err = retval;
9276                         return BLOCK_ABORT;
9277                 }
9278                 es->num--;
9279                 retval = ext2fs_write_dir_block(fs, new_blk, block);
9280         } else {
9281                 retval = ext2fs_get_mem(fs->blocksize, &block);
9282                 if (retval) {
9283                         es->err = retval;
9284                         return BLOCK_ABORT;
9285                 }
9286                 memset(block, 0, fs->blocksize);
9287                 retval = io_channel_write_blk(fs->io, new_blk, 1, block);
9288         }
9289         if (retval) {
9290                 es->err = retval;
9291                 return BLOCK_ABORT;
9292         }
9293         ext2fs_free_mem(&block);
9294         *blocknr = new_blk;
9295         ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
9296         ext2fs_block_alloc_stats(fs, new_blk, +1);
9297         es->newblocks++;
9298
9299         if (es->num == 0)
9300                 return (BLOCK_CHANGED | BLOCK_ABORT);
9301         else
9302                 return BLOCK_CHANGED;
9303 }
9304
9305 errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
9306                                   int num, int guaranteed_size)
9307 {
9308         ext2_filsys fs = ctx->fs;
9309         errcode_t       retval;
9310         struct expand_dir_struct es;
9311         struct ext2_inode       inode;
9312
9313         if (!(fs->flags & EXT2_FLAG_RW))
9314                 return EXT2_ET_RO_FILSYS;
9315
9316         /*
9317          * Read the inode and block bitmaps in; we'll be messing with
9318          * them.
9319          */
9320         e2fsck_read_bitmaps(ctx);
9321
9322         retval = ext2fs_check_directory(fs, dir);
9323         if (retval)
9324                 return retval;
9325
9326         es.num = num;
9327         es.guaranteed_size = guaranteed_size;
9328         es.last_block = 0;
9329         es.err = 0;
9330         es.newblocks = 0;
9331         es.ctx = ctx;
9332
9333         retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
9334                                        0, expand_dir_proc, &es);
9335
9336         if (es.err)
9337                 return es.err;
9338
9339         /*
9340          * Update the size and block count fields in the inode.
9341          */
9342         retval = ext2fs_read_inode(fs, dir, &inode);
9343         if (retval)
9344                 return retval;
9345
9346         inode.i_size = (es.last_block + 1) * fs->blocksize;
9347         inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
9348
9349         e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
9350
9351         return 0;
9352 }
9353
9354 /*
9355  * pass4.c -- pass #4 of e2fsck: Check reference counts
9356  *
9357  * Pass 4 frees the following data structures:
9358  *      - A bitmap of which inodes are in bad blocks.   (inode_bb_map)
9359  *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
9360  */
9361
9362 /*
9363  * This routine is called when an inode is not connected to the
9364  * directory tree.
9365  *
9366  * This subroutine returns 1 then the caller shouldn't bother with the
9367  * rest of the pass 4 tests.
9368  */
9369 static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
9370 {
9371         ext2_filsys fs = ctx->fs;
9372         struct ext2_inode       inode;
9373         struct problem_context  pctx;
9374
9375         e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
9376         clear_problem_context(&pctx);
9377         pctx.ino = i;
9378         pctx.inode = &inode;
9379
9380         /*
9381          * Offer to delete any zero-length files that does not have
9382          * blocks.  If there is an EA block, it might have useful
9383          * information, so we won't prompt to delete it, but let it be
9384          * reconnected to lost+found.
9385          */
9386         if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
9387                                 LINUX_S_ISDIR(inode.i_mode))) {
9388                 if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
9389                         ext2fs_icount_store(ctx->inode_link_info, i, 0);
9390                         inode.i_links_count = 0;
9391                         inode.i_dtime = time(0);
9392                         e2fsck_write_inode(ctx, i, &inode,
9393                                            "disconnect_inode");
9394                         /*
9395                          * Fix up the bitmaps...
9396                          */
9397                         e2fsck_read_bitmaps(ctx);
9398                         ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
9399                         ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
9400                         ext2fs_inode_alloc_stats2(fs, i, -1,
9401                                                   LINUX_S_ISDIR(inode.i_mode));
9402                         return 0;
9403                 }
9404         }
9405
9406         /*
9407          * Prompt to reconnect.
9408          */
9409         if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
9410                 if (e2fsck_reconnect_file(ctx, i))
9411                         ext2fs_unmark_valid(fs);
9412         } else {
9413                 /*
9414                  * If we don't attach the inode, then skip the
9415                  * i_links_test since there's no point in trying to
9416                  * force i_links_count to zero.
9417                  */
9418                 ext2fs_unmark_valid(fs);
9419                 return 1;
9420         }
9421         return 0;
9422 }
9423
9424
9425 static void e2fsck_pass4(e2fsck_t ctx)
9426 {
9427         ext2_filsys fs = ctx->fs;
9428         ext2_ino_t      i;
9429         struct ext2_inode       inode;
9430 #ifdef RESOURCE_TRACK
9431         struct resource_track   rtrack;
9432 #endif
9433         struct problem_context  pctx;
9434         __u16   link_count, link_counted;
9435         char    *buf = 0;
9436         int     group, maxgroup;
9437
9438 #ifdef RESOURCE_TRACK
9439         init_resource_track(&rtrack);
9440 #endif
9441
9442 #ifdef MTRACE
9443         mtrace_print("Pass 4");
9444 #endif
9445
9446         clear_problem_context(&pctx);
9447
9448         if (!(ctx->options & E2F_OPT_PREEN))
9449                 fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
9450
9451         group = 0;
9452         maxgroup = fs->group_desc_count;
9453         if (ctx->progress)
9454                 if ((ctx->progress)(ctx, 4, 0, maxgroup))
9455                         return;
9456
9457         for (i=1; i <= fs->super->s_inodes_count; i++) {
9458                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
9459                         return;
9460                 if ((i % fs->super->s_inodes_per_group) == 0) {
9461                         group++;
9462                         if (ctx->progress)
9463                                 if ((ctx->progress)(ctx, 4, group, maxgroup))
9464                                         return;
9465                 }
9466                 if (i == EXT2_BAD_INO ||
9467                     (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
9468                         continue;
9469                 if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
9470                     (ctx->inode_imagic_map &&
9471                      ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)) ||
9472                     (ctx->inode_bb_map &&
9473                      ext2fs_test_inode_bitmap(ctx->inode_bb_map, i)))
9474                         continue;
9475                 ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
9476                 ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
9477                 if (link_counted == 0) {
9478                         if (!buf)
9479                                 buf = e2fsck_allocate_memory(ctx,
9480                                      fs->blocksize, "bad_inode buffer");
9481                         if (e2fsck_process_bad_inode(ctx, 0, i, buf))
9482                                 continue;
9483                         if (disconnect_inode(ctx, i))
9484                                 continue;
9485                         ext2fs_icount_fetch(ctx->inode_link_info, i,
9486                                             &link_count);
9487                         ext2fs_icount_fetch(ctx->inode_count, i,
9488                                             &link_counted);
9489                 }
9490                 if (link_counted != link_count) {
9491                         e2fsck_read_inode(ctx, i, &inode, "pass4");
9492                         pctx.ino = i;
9493                         pctx.inode = &inode;
9494                         if (link_count != inode.i_links_count) {
9495                                 pctx.num = link_count;
9496                                 fix_problem(ctx,
9497                                             PR_4_INCONSISTENT_COUNT, &pctx);
9498                         }
9499                         pctx.num = link_counted;
9500                         if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
9501                                 inode.i_links_count = link_counted;
9502                                 e2fsck_write_inode(ctx, i, &inode, "pass4");
9503                         }
9504                 }
9505         }
9506         ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
9507         ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
9508         ext2fs_free_inode_bitmap(ctx->inode_bb_map);
9509         ctx->inode_bb_map = 0;
9510         ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
9511         ctx->inode_imagic_map = 0;
9512         if (buf)
9513                 ext2fs_free_mem(&buf);
9514 #ifdef RESOURCE_TRACK
9515         if (ctx->options & E2F_OPT_TIME2) {
9516                 e2fsck_clear_progbar(ctx);
9517                 print_resource_track(_("Pass 4"), &rtrack);
9518         }
9519 #endif
9520 }
9521
9522 /*
9523  * pass5.c --- check block and inode bitmaps against on-disk bitmaps
9524  */
9525
9526 #define NO_BLK ((blk_t) -1)
9527
9528 static void print_bitmap_problem(e2fsck_t ctx, int problem,
9529                             struct problem_context *pctx)
9530 {
9531         switch (problem) {
9532         case PR_5_BLOCK_UNUSED:
9533                 if (pctx->blk == pctx->blk2)
9534                         pctx->blk2 = 0;
9535                 else
9536                         problem = PR_5_BLOCK_RANGE_UNUSED;
9537                 break;
9538         case PR_5_BLOCK_USED:
9539                 if (pctx->blk == pctx->blk2)
9540                         pctx->blk2 = 0;
9541                 else
9542                         problem = PR_5_BLOCK_RANGE_USED;
9543                 break;
9544         case PR_5_INODE_UNUSED:
9545                 if (pctx->ino == pctx->ino2)
9546                         pctx->ino2 = 0;
9547                 else
9548                         problem = PR_5_INODE_RANGE_UNUSED;
9549                 break;
9550         case PR_5_INODE_USED:
9551                 if (pctx->ino == pctx->ino2)
9552                         pctx->ino2 = 0;
9553                 else
9554                         problem = PR_5_INODE_RANGE_USED;
9555                 break;
9556         }
9557         fix_problem(ctx, problem, pctx);
9558         pctx->blk = pctx->blk2 = NO_BLK;
9559         pctx->ino = pctx->ino2 = 0;
9560 }
9561
9562 static void check_block_bitmaps(e2fsck_t ctx)
9563 {
9564         ext2_filsys fs = ctx->fs;
9565         blk_t   i;
9566         int     *free_array;
9567         int     group = 0;
9568         unsigned int    blocks = 0;
9569         unsigned int    free_blocks = 0;
9570         int     group_free = 0;
9571         int     actual, bitmap;
9572         struct problem_context  pctx;
9573         int     problem, save_problem, fixit, had_problem;
9574         errcode_t       retval;
9575
9576         clear_problem_context(&pctx);
9577         free_array = (int *) e2fsck_allocate_memory(ctx,
9578             fs->group_desc_count * sizeof(int), "free block count array");
9579
9580         if ((fs->super->s_first_data_block <
9581              ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
9582             (fs->super->s_blocks_count-1 >
9583              ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
9584                 pctx.num = 1;
9585                 pctx.blk = fs->super->s_first_data_block;
9586                 pctx.blk2 = fs->super->s_blocks_count -1;
9587                 pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
9588                 pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
9589                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9590
9591                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9592                 return;
9593         }
9594
9595         if ((fs->super->s_first_data_block <
9596              ext2fs_get_block_bitmap_start(fs->block_map)) ||
9597             (fs->super->s_blocks_count-1 >
9598              ext2fs_get_block_bitmap_end(fs->block_map))) {
9599                 pctx.num = 2;
9600                 pctx.blk = fs->super->s_first_data_block;
9601                 pctx.blk2 = fs->super->s_blocks_count -1;
9602                 pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
9603                 pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
9604                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9605
9606                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9607                 return;
9608         }
9609
9610 redo_counts:
9611         had_problem = 0;
9612         save_problem = 0;
9613         pctx.blk = pctx.blk2 = NO_BLK;
9614         for (i = fs->super->s_first_data_block;
9615              i < fs->super->s_blocks_count;
9616              i++) {
9617                 actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
9618                 bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
9619
9620                 if (actual == bitmap)
9621                         goto do_counts;
9622
9623                 if (!actual && bitmap) {
9624                         /*
9625                          * Block not used, but marked in use in the bitmap.
9626                          */
9627                         problem = PR_5_BLOCK_UNUSED;
9628                 } else {
9629                         /*
9630                          * Block used, but not marked in use in the bitmap.
9631                          */
9632                         problem = PR_5_BLOCK_USED;
9633                 }
9634                 if (pctx.blk == NO_BLK) {
9635                         pctx.blk = pctx.blk2 = i;
9636                         save_problem = problem;
9637                 } else {
9638                         if ((problem == save_problem) &&
9639                             (pctx.blk2 == i-1))
9640                                 pctx.blk2++;
9641                         else {
9642                                 print_bitmap_problem(ctx, save_problem, &pctx);
9643                                 pctx.blk = pctx.blk2 = i;
9644                                 save_problem = problem;
9645                         }
9646                 }
9647                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
9648                 had_problem++;
9649
9650         do_counts:
9651                 if (!bitmap) {
9652                         group_free++;
9653                         free_blocks++;
9654                 }
9655                 blocks ++;
9656                 if ((blocks == fs->super->s_blocks_per_group) ||
9657                     (i == fs->super->s_blocks_count-1)) {
9658                         free_array[group] = group_free;
9659                         group ++;
9660                         blocks = 0;
9661                         group_free = 0;
9662                         if (ctx->progress)
9663                                 if ((ctx->progress)(ctx, 5, group,
9664                                                     fs->group_desc_count*2))
9665                                         return;
9666                 }
9667         }
9668         if (pctx.blk != NO_BLK)
9669                 print_bitmap_problem(ctx, save_problem, &pctx);
9670         if (had_problem)
9671                 fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
9672         else
9673                 fixit = -1;
9674         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
9675
9676         if (fixit == 1) {
9677                 ext2fs_free_block_bitmap(fs->block_map);
9678                 retval = ext2fs_copy_bitmap(ctx->block_found_map,
9679                                                   &fs->block_map);
9680                 if (retval) {
9681                         clear_problem_context(&pctx);
9682                         fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
9683                         ctx->flags |= E2F_FLAG_ABORT;
9684                         return;
9685                 }
9686                 ext2fs_set_bitmap_padding(fs->block_map);
9687                 ext2fs_mark_bb_dirty(fs);
9688
9689                 /* Redo the counts */
9690                 blocks = 0; free_blocks = 0; group_free = 0; group = 0;
9691                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
9692                 goto redo_counts;
9693         } else if (fixit == 0)
9694                 ext2fs_unmark_valid(fs);
9695
9696         for (i = 0; i < fs->group_desc_count; i++) {
9697                 if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
9698                         pctx.group = i;
9699                         pctx.blk = fs->group_desc[i].bg_free_blocks_count;
9700                         pctx.blk2 = free_array[i];
9701
9702                         if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
9703                                         &pctx)) {
9704                                 fs->group_desc[i].bg_free_blocks_count =
9705                                         free_array[i];
9706                                 ext2fs_mark_super_dirty(fs);
9707                         } else
9708                                 ext2fs_unmark_valid(fs);
9709                 }
9710         }
9711         if (free_blocks != fs->super->s_free_blocks_count) {
9712                 pctx.group = 0;
9713                 pctx.blk = fs->super->s_free_blocks_count;
9714                 pctx.blk2 = free_blocks;
9715
9716                 if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
9717                         fs->super->s_free_blocks_count = free_blocks;
9718                         ext2fs_mark_super_dirty(fs);
9719                 } else
9720                         ext2fs_unmark_valid(fs);
9721         }
9722         ext2fs_free_mem(&free_array);
9723 }
9724
9725 static void check_inode_bitmaps(e2fsck_t ctx)
9726 {
9727         ext2_filsys fs = ctx->fs;
9728         ext2_ino_t      i;
9729         unsigned int    free_inodes = 0;
9730         int             group_free = 0;
9731         int             dirs_count = 0;
9732         int             group = 0;
9733         unsigned int    inodes = 0;
9734         int             *free_array;
9735         int             *dir_array;
9736         int             actual, bitmap;
9737         errcode_t       retval;
9738         struct problem_context  pctx;
9739         int             problem, save_problem, fixit, had_problem;
9740
9741         clear_problem_context(&pctx);
9742         free_array = (int *) e2fsck_allocate_memory(ctx,
9743             fs->group_desc_count * sizeof(int), "free inode count array");
9744
9745         dir_array = (int *) e2fsck_allocate_memory(ctx,
9746            fs->group_desc_count * sizeof(int), "directory count array");
9747
9748         if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
9749             (fs->super->s_inodes_count >
9750              ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
9751                 pctx.num = 3;
9752                 pctx.blk = 1;
9753                 pctx.blk2 = fs->super->s_inodes_count;
9754                 pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
9755                 pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
9756                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9757
9758                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9759                 return;
9760         }
9761         if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
9762             (fs->super->s_inodes_count >
9763              ext2fs_get_inode_bitmap_end(fs->inode_map))) {
9764                 pctx.num = 4;
9765                 pctx.blk = 1;
9766                 pctx.blk2 = fs->super->s_inodes_count;
9767                 pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
9768                 pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
9769                 fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
9770
9771                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9772                 return;
9773         }
9774
9775 redo_counts:
9776         had_problem = 0;
9777         save_problem = 0;
9778         pctx.ino = pctx.ino2 = 0;
9779         for (i = 1; i <= fs->super->s_inodes_count; i++) {
9780                 actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
9781                 bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
9782
9783                 if (actual == bitmap)
9784                         goto do_counts;
9785
9786                 if (!actual && bitmap) {
9787                         /*
9788                          * Inode wasn't used, but marked in bitmap
9789                          */
9790                         problem = PR_5_INODE_UNUSED;
9791                 } else /* if (actual && !bitmap) */ {
9792                         /*
9793                          * Inode used, but not in bitmap
9794                          */
9795                         problem = PR_5_INODE_USED;
9796                 }
9797                 if (pctx.ino == 0) {
9798                         pctx.ino = pctx.ino2 = i;
9799                         save_problem = problem;
9800                 } else {
9801                         if ((problem == save_problem) &&
9802                             (pctx.ino2 == i-1))
9803                                 pctx.ino2++;
9804                         else {
9805                                 print_bitmap_problem(ctx, save_problem, &pctx);
9806                                 pctx.ino = pctx.ino2 = i;
9807                                 save_problem = problem;
9808                         }
9809                 }
9810                 ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
9811                 had_problem++;
9812
9813 do_counts:
9814                 if (!bitmap) {
9815                         group_free++;
9816                         free_inodes++;
9817                 } else {
9818                         if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
9819                                 dirs_count++;
9820                 }
9821                 inodes++;
9822                 if ((inodes == fs->super->s_inodes_per_group) ||
9823                     (i == fs->super->s_inodes_count)) {
9824                         free_array[group] = group_free;
9825                         dir_array[group] = dirs_count;
9826                         group ++;
9827                         inodes = 0;
9828                         group_free = 0;
9829                         dirs_count = 0;
9830                         if (ctx->progress)
9831                                 if ((ctx->progress)(ctx, 5,
9832                                             group + fs->group_desc_count,
9833                                             fs->group_desc_count*2))
9834                                         return;
9835                 }
9836         }
9837         if (pctx.ino)
9838                 print_bitmap_problem(ctx, save_problem, &pctx);
9839
9840         if (had_problem)
9841                 fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
9842         else
9843                 fixit = -1;
9844         ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
9845
9846         if (fixit == 1) {
9847                 ext2fs_free_inode_bitmap(fs->inode_map);
9848                 retval = ext2fs_copy_bitmap(ctx->inode_used_map,
9849                                                   &fs->inode_map);
9850                 if (retval) {
9851                         clear_problem_context(&pctx);
9852                         fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
9853                         ctx->flags |= E2F_FLAG_ABORT;
9854                         return;
9855                 }
9856                 ext2fs_set_bitmap_padding(fs->inode_map);
9857                 ext2fs_mark_ib_dirty(fs);
9858
9859                 /* redo counts */
9860                 inodes = 0; free_inodes = 0; group_free = 0;
9861                 dirs_count = 0; group = 0;
9862                 memset(free_array, 0, fs->group_desc_count * sizeof(int));
9863                 memset(dir_array, 0, fs->group_desc_count * sizeof(int));
9864                 goto redo_counts;
9865         } else if (fixit == 0)
9866                 ext2fs_unmark_valid(fs);
9867
9868         for (i = 0; i < fs->group_desc_count; i++) {
9869                 if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
9870                         pctx.group = i;
9871                         pctx.ino = fs->group_desc[i].bg_free_inodes_count;
9872                         pctx.ino2 = free_array[i];
9873                         if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
9874                                         &pctx)) {
9875                                 fs->group_desc[i].bg_free_inodes_count =
9876                                         free_array[i];
9877                                 ext2fs_mark_super_dirty(fs);
9878                         } else
9879                                 ext2fs_unmark_valid(fs);
9880                 }
9881                 if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
9882                         pctx.group = i;
9883                         pctx.ino = fs->group_desc[i].bg_used_dirs_count;
9884                         pctx.ino2 = dir_array[i];
9885
9886                         if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
9887                                         &pctx)) {
9888                                 fs->group_desc[i].bg_used_dirs_count =
9889                                         dir_array[i];
9890                                 ext2fs_mark_super_dirty(fs);
9891                         } else
9892                                 ext2fs_unmark_valid(fs);
9893                 }
9894         }
9895         if (free_inodes != fs->super->s_free_inodes_count) {
9896                 pctx.group = -1;
9897                 pctx.ino = fs->super->s_free_inodes_count;
9898                 pctx.ino2 = free_inodes;
9899
9900                 if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
9901                         fs->super->s_free_inodes_count = free_inodes;
9902                         ext2fs_mark_super_dirty(fs);
9903                 } else
9904                         ext2fs_unmark_valid(fs);
9905         }
9906         ext2fs_free_mem(&free_array);
9907         ext2fs_free_mem(&dir_array);
9908 }
9909
9910 static void check_inode_end(e2fsck_t ctx)
9911 {
9912         ext2_filsys fs = ctx->fs;
9913         ext2_ino_t      end, save_inodes_count, i;
9914         struct problem_context  pctx;
9915
9916         clear_problem_context(&pctx);
9917
9918         end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
9919         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
9920                                                      &save_inodes_count);
9921         if (pctx.errcode) {
9922                 pctx.num = 1;
9923                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9924                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9925                 return;
9926         }
9927         if (save_inodes_count == end)
9928                 return;
9929
9930         for (i = save_inodes_count + 1; i <= end; i++) {
9931                 if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
9932                         if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
9933                                 for (i = save_inodes_count + 1; i <= end; i++)
9934                                         ext2fs_mark_inode_bitmap(fs->inode_map,
9935                                                                  i);
9936                                 ext2fs_mark_ib_dirty(fs);
9937                         } else
9938                                 ext2fs_unmark_valid(fs);
9939                         break;
9940                 }
9941         }
9942
9943         pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
9944                                                      save_inodes_count, 0);
9945         if (pctx.errcode) {
9946                 pctx.num = 2;
9947                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9948                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9949                 return;
9950         }
9951 }
9952
9953 static void check_block_end(e2fsck_t ctx)
9954 {
9955         ext2_filsys fs = ctx->fs;
9956         blk_t   end, save_blocks_count, i;
9957         struct problem_context  pctx;
9958
9959         clear_problem_context(&pctx);
9960
9961         end = fs->block_map->start +
9962                 (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
9963         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
9964                                                      &save_blocks_count);
9965         if (pctx.errcode) {
9966                 pctx.num = 3;
9967                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9968                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9969                 return;
9970         }
9971         if (save_blocks_count == end)
9972                 return;
9973
9974         for (i = save_blocks_count + 1; i <= end; i++) {
9975                 if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
9976                         if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
9977                                 for (i = save_blocks_count + 1; i <= end; i++)
9978                                         ext2fs_mark_block_bitmap(fs->block_map,
9979                                                                  i);
9980                                 ext2fs_mark_bb_dirty(fs);
9981                         } else
9982                                 ext2fs_unmark_valid(fs);
9983                         break;
9984                 }
9985         }
9986
9987         pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
9988                                                      save_blocks_count, 0);
9989         if (pctx.errcode) {
9990                 pctx.num = 4;
9991                 fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
9992                 ctx->flags |= E2F_FLAG_ABORT; /* fatal */
9993                 return;
9994         }
9995 }
9996
9997 static void e2fsck_pass5(e2fsck_t ctx)
9998 {
9999 #ifdef RESOURCE_TRACK
10000         struct resource_track   rtrack;
10001 #endif
10002         struct problem_context  pctx;
10003
10004 #ifdef MTRACE
10005         mtrace_print("Pass 5");
10006 #endif
10007
10008 #ifdef RESOURCE_TRACK
10009         init_resource_track(&rtrack);
10010 #endif
10011
10012         clear_problem_context(&pctx);
10013
10014         if (!(ctx->options & E2F_OPT_PREEN))
10015                 fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
10016
10017         if (ctx->progress)
10018                 if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
10019                         return;
10020
10021         e2fsck_read_bitmaps(ctx);
10022
10023         check_block_bitmaps(ctx);
10024         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
10025                 return;
10026         check_inode_bitmaps(ctx);
10027         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
10028                 return;
10029         check_inode_end(ctx);
10030         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
10031                 return;
10032         check_block_end(ctx);
10033         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
10034                 return;
10035
10036         ext2fs_free_inode_bitmap(ctx->inode_used_map);
10037         ctx->inode_used_map = 0;
10038         ext2fs_free_inode_bitmap(ctx->inode_dir_map);
10039         ctx->inode_dir_map = 0;
10040         ext2fs_free_block_bitmap(ctx->block_found_map);
10041         ctx->block_found_map = 0;
10042
10043 #ifdef RESOURCE_TRACK
10044         if (ctx->options & E2F_OPT_TIME2) {
10045                 e2fsck_clear_progbar(ctx);
10046                 print_resource_track(_("Pass 5"), &rtrack);
10047         }
10048 #endif
10049 }
10050
10051 /*
10052  * problem.c --- report filesystem problems to the user
10053  */
10054
10055 #define PR_PREEN_OK     0x000001 /* Don't need to do preenhalt */
10056 #define PR_NO_OK        0x000002 /* If user answers no, don't make fs invalid */
10057 #define PR_NO_DEFAULT   0x000004 /* Default to no */
10058 #define PR_MSG_ONLY     0x000008 /* Print message only */
10059
10060 /* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
10061
10062 #define PR_FATAL        0x001000 /* Fatal error */
10063 #define PR_AFTER_CODE   0x002000 /* After asking the first question, */
10064                                  /* ask another */
10065 #define PR_PREEN_NOMSG  0x004000 /* Don't print a message if we're preening */
10066 #define PR_NOCOLLATE    0x008000 /* Don't collate answers for this latch */
10067 #define PR_NO_NOMSG     0x010000 /* Don't print a message if e2fsck -n */
10068 #define PR_PREEN_NO     0x020000 /* Use No as an answer if preening */
10069 #define PR_PREEN_NOHDR  0x040000 /* Don't print the preen header */
10070
10071
10072 #define PROMPT_NONE     0
10073 #define PROMPT_FIX      1
10074 #define PROMPT_CLEAR    2
10075 #define PROMPT_RELOCATE 3
10076 #define PROMPT_ALLOCATE 4
10077 #define PROMPT_EXPAND   5
10078 #define PROMPT_CONNECT  6
10079 #define PROMPT_CREATE   7
10080 #define PROMPT_SALVAGE  8
10081 #define PROMPT_TRUNCATE 9
10082 #define PROMPT_CLEAR_INODE 10
10083 #define PROMPT_ABORT    11
10084 #define PROMPT_SPLIT    12
10085 #define PROMPT_CONTINUE 13
10086 #define PROMPT_CLONE    14
10087 #define PROMPT_DELETE   15
10088 #define PROMPT_SUPPRESS 16
10089 #define PROMPT_UNLINK   17
10090 #define PROMPT_CLEAR_HTREE 18
10091 #define PROMPT_RECREATE 19
10092 #define PROMPT_NULL     20
10093
10094 struct e2fsck_problem {
10095         problem_t       e2p_code;
10096         const char *    e2p_description;
10097         char            prompt;
10098         int             flags;
10099         problem_t       second_code;
10100 };
10101
10102 struct latch_descr {
10103         int             latch_code;
10104         problem_t       question;
10105         problem_t       end_message;
10106         int             flags;
10107 };
10108
10109 /*
10110  * These are the prompts which are used to ask the user if they want
10111  * to fix a problem.
10112  */
10113 static const char * const prompt[] = {
10114         N_("(no prompt)"),      /* 0 */
10115         N_("Fix"),              /* 1 */
10116         N_("Clear"),            /* 2 */
10117         N_("Relocate"),         /* 3 */
10118         N_("Allocate"),         /* 4 */
10119         N_("Expand"),           /* 5 */
10120         N_("Connect to /lost+found"), /* 6 */
10121         N_("Create"),           /* 7 */
10122         N_("Salvage"),          /* 8 */
10123         N_("Truncate"),         /* 9 */
10124         N_("Clear inode"),      /* 10 */
10125         N_("Abort"),            /* 11 */
10126         N_("Split"),            /* 12 */
10127         N_("Continue"),         /* 13 */
10128         N_("Clone duplicate/bad blocks"), /* 14 */
10129         N_("Delete file"),      /* 15 */
10130         N_("Suppress messages"),/* 16 */
10131         N_("Unlink"),           /* 17 */
10132         N_("Clear HTree index"),/* 18 */
10133         N_("Recreate"),         /* 19 */
10134         "",                     /* 20 */
10135 };
10136
10137 /*
10138  * These messages are printed when we are preen mode and we will be
10139  * automatically fixing the problem.
10140  */
10141 static const char * const preen_msg[] = {
10142         N_("(NONE)"),           /* 0 */
10143         N_("FIXED"),            /* 1 */
10144         N_("CLEARED"),          /* 2 */
10145         N_("RELOCATED"),        /* 3 */
10146         N_("ALLOCATED"),        /* 4 */
10147         N_("EXPANDED"),         /* 5 */
10148         N_("RECONNECTED"),      /* 6 */
10149         N_("CREATED"),          /* 7 */
10150         N_("SALVAGED"),         /* 8 */
10151         N_("TRUNCATED"),        /* 9 */
10152         N_("INODE CLEARED"),    /* 10 */
10153         N_("ABORTED"),          /* 11 */
10154         N_("SPLIT"),            /* 12 */
10155         N_("CONTINUING"),       /* 13 */
10156         N_("DUPLICATE/BAD BLOCKS CLONED"), /* 14 */
10157         N_("FILE DELETED"),     /* 15 */
10158         N_("SUPPRESSED"),       /* 16 */
10159         N_("UNLINKED"),         /* 17 */
10160         N_("HTREE INDEX CLEARED"),/* 18 */
10161         N_("WILL RECREATE"),    /* 19 */
10162         "",                     /* 20 */
10163 };
10164
10165 static const struct e2fsck_problem problem_table[] = {
10166
10167         /* Pre-Pass 1 errors */
10168
10169         /* Block bitmap not in group */
10170         { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g.  (@b %b)\n"),
10171           PROMPT_RELOCATE, PR_LATCH_RELOC },
10172
10173         /* Inode bitmap not in group */
10174         { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g.  (@b %b)\n"),
10175           PROMPT_RELOCATE, PR_LATCH_RELOC },
10176
10177         /* Inode table not in group */
10178         { PR_0_ITABLE_NOT_GROUP,
10179           N_("@i table for @g %g is not in @g.  (@b %b)\n"
10180           "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
10181           PROMPT_RELOCATE, PR_LATCH_RELOC },
10182
10183         /* Superblock corrupt */
10184         { PR_0_SB_CORRUPT,
10185           N_("\nThe @S could not be read or does not describe a correct ext2\n"
10186           "@f.  If the @v is valid and it really contains an ext2\n"
10187           "@f (and not swap or ufs or something else), then the @S\n"
10188           "is corrupt, and you might try running e2fsck with an alternate @S:\n"
10189           "    e2fsck -b %S <@v>\n\n"),
10190           PROMPT_NONE, PR_FATAL },
10191
10192         /* Filesystem size is wrong */
10193         { PR_0_FS_SIZE_WRONG,
10194           N_("The @f size (according to the @S) is %b @bs\n"
10195           "The physical size of the @v is %c @bs\n"
10196           "Either the @S or the partition table is likely to be corrupt!\n"),
10197           PROMPT_ABORT, 0 },
10198
10199         /* Fragments not supported */
10200         { PR_0_NO_FRAGMENTS,
10201           N_("@S @b_size = %b, fragsize = %c.\n"
10202           "This version of e2fsck does not support fragment sizes different\n"
10203           "from the @b size.\n"),
10204           PROMPT_NONE, PR_FATAL },
10205
10206           /* Bad blocks_per_group */
10207         { PR_0_BLOCKS_PER_GROUP,
10208           N_("@S @bs_per_group = %b, should have been %c\n"),
10209           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
10210
10211         /* Bad first_data_block */
10212         { PR_0_FIRST_DATA_BLOCK,
10213           N_("@S first_data_@b = %b, should have been %c\n"),
10214           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
10215
10216         /* Adding UUID to filesystem */
10217         { PR_0_ADD_UUID,
10218           N_("@f did not have a UUID; generating one.\n\n"),
10219           PROMPT_NONE, 0 },
10220
10221         /* Relocate hint */
10222         { PR_0_RELOCATE_HINT,
10223           N_("Note: if there is several inode or block bitmap blocks\n"
10224           "which require relocation, or one part of the inode table\n"
10225           "which must be moved, you may wish to try running e2fsck\n"
10226           "with the '-b %S' option first.  The problem may lie only\n"
10227           "with the primary block group descriptor, and the backup\n"
10228           "block group descriptor may be OK.\n\n"),
10229           PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
10230
10231         /* Miscellaneous superblock corruption */
10232         { PR_0_MISC_CORRUPT_SUPER,
10233           N_("Corruption found in @S.  (%s = %N).\n"),
10234           PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
10235
10236         /* Error determing physical device size of filesystem */
10237         { PR_0_GETSIZE_ERROR,
10238           N_("Error determining size of the physical @v: %m\n"),
10239           PROMPT_NONE, PR_FATAL },
10240
10241         /* Inode count in superblock is incorrect */
10242         { PR_0_INODE_COUNT_WRONG,
10243           N_("@i count in @S is %i, should be %j.\n"),
10244           PROMPT_FIX, 0 },
10245
10246         { PR_0_HURD_CLEAR_FILETYPE,
10247           N_("The Hurd does not support the filetype feature.\n"),
10248           PROMPT_CLEAR, 0 },
10249
10250         /* Journal inode is invalid */
10251         { PR_0_JOURNAL_BAD_INODE,
10252           N_("@S has a bad ext3 @j (@i %i).\n"),
10253           PROMPT_CLEAR, PR_PREEN_OK },
10254
10255         /* The external journal has (unsupported) multiple filesystems */
10256         { PR_0_JOURNAL_UNSUPP_MULTIFS,
10257           N_("External @j has multiple @f users (unsupported).\n"),
10258           PROMPT_NONE, PR_FATAL },
10259
10260         /* Can't find external journal */
10261         { PR_0_CANT_FIND_JOURNAL,
10262           N_("Can't find external @j\n"),
10263           PROMPT_NONE, PR_FATAL },
10264
10265         /* External journal has bad superblock */
10266         { PR_0_EXT_JOURNAL_BAD_SUPER,
10267           N_("External @j has bad @S\n"),
10268           PROMPT_NONE, PR_FATAL },
10269
10270         /* Superblock has a bad journal UUID */
10271         { PR_0_JOURNAL_BAD_UUID,
10272           N_("External @j does not support this @f\n"),
10273           PROMPT_NONE, PR_FATAL },
10274
10275         /* Journal has an unknown superblock type */
10276         { PR_0_JOURNAL_UNSUPP_SUPER,
10277           N_("Ext3 @j @S is unknown type %N (unsupported).\n"
10278              "It is likely that your copy of e2fsck is old and/or doesn't "
10279              "support this @j format.\n"
10280              "It is also possible the @j @S is corrupt.\n"),
10281           PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
10282
10283         /* Journal superblock is corrupt */
10284         { PR_0_JOURNAL_BAD_SUPER,
10285           N_("Ext3 @j @S is corrupt.\n"),
10286           PROMPT_FIX, PR_PREEN_OK },
10287
10288         /* Superblock flag should be cleared */
10289         { PR_0_JOURNAL_HAS_JOURNAL,
10290           N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
10291           PROMPT_CLEAR, PR_PREEN_OK },
10292
10293         /* Superblock flag is incorrect */
10294         { PR_0_JOURNAL_RECOVER_SET,
10295           N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
10296           PROMPT_CLEAR, PR_PREEN_OK },
10297
10298         /* Journal has data, but recovery flag is clear */
10299         { PR_0_JOURNAL_RECOVERY_CLEAR,
10300           N_("ext3 recovery flag clear, but @j has data.\n"),
10301           PROMPT_NONE, 0 },
10302
10303         /* Ask if we should clear the journal */
10304         { PR_0_JOURNAL_RESET_JOURNAL,
10305           N_("Clear @j"),
10306           PROMPT_NULL, PR_PREEN_NOMSG },
10307
10308         /* Ask if we should run the journal anyway */
10309         { PR_0_JOURNAL_RUN,
10310           N_("Run @j anyway"),
10311           PROMPT_NULL, 0 },
10312
10313         /* Run the journal by default */
10314         { PR_0_JOURNAL_RUN_DEFAULT,
10315           N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
10316           PROMPT_NONE, 0 },
10317
10318         /* Clearing orphan inode */
10319         { PR_0_ORPHAN_CLEAR_INODE,
10320           N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
10321           PROMPT_NONE, 0 },
10322
10323         /* Illegal block found in orphaned inode */
10324         { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
10325            N_("@I @b #%B (%b) found in @o @i %i.\n"),
10326           PROMPT_NONE, 0 },
10327
10328         /* Already cleared block found in orphaned inode */
10329         { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
10330            N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
10331           PROMPT_NONE, 0 },
10332
10333         /* Illegal orphan inode in superblock */
10334         { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
10335           N_("@I @o @i %i in @S.\n"),
10336           PROMPT_NONE, 0 },
10337
10338         /* Illegal inode in orphaned inode list */
10339         { PR_0_ORPHAN_ILLEGAL_INODE,
10340           N_("@I @i %i in @o @i list.\n"),
10341           PROMPT_NONE, 0 },
10342
10343         /* Filesystem revision is 0, but feature flags are set */
10344         { PR_0_FS_REV_LEVEL,
10345           "@f has feature flag(s) set, but is a revision 0 @f.  ",
10346           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
10347
10348         /* Journal superblock has an unknown read-only feature flag set */
10349         { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
10350           N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
10351           PROMPT_ABORT, 0 },
10352
10353         /* Journal superblock has an unknown incompatible feature flag set */
10354         { PR_0_JOURNAL_UNSUPP_INCOMPAT,
10355           N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
10356           PROMPT_ABORT, 0 },
10357
10358         /* Journal has unsupported version number */
10359         { PR_0_JOURNAL_UNSUPP_VERSION,
10360           N_("@j version not supported by this e2fsck.\n"),
10361           PROMPT_ABORT, 0 },
10362
10363         /* Moving journal to hidden file */
10364         { PR_0_MOVE_JOURNAL,
10365           N_("Moving @j from /%s to hidden inode.\n\n"),
10366           PROMPT_NONE, 0 },
10367
10368         /* Error moving journal to hidden file */
10369         { PR_0_ERR_MOVE_JOURNAL,
10370           N_("Error moving @j: %m\n\n"),
10371           PROMPT_NONE, 0 },
10372
10373         /* Clearing V2 journal superblock */
10374         { PR_0_CLEAR_V2_JOURNAL,
10375           N_("Found invalid V2 @j @S fields (from V1 journal).\n"
10376              "Clearing fields beyond the V1 @j @S...\n\n"),
10377           PROMPT_NONE, 0 },
10378
10379         /* Backup journal inode blocks */
10380         { PR_0_BACKUP_JNL,
10381           N_("Backing up @j @i @b information.\n\n"),
10382           PROMPT_NONE, 0 },
10383
10384         /* Reserved blocks w/o resize_inode */
10385         { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
10386           N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
10387              "is %N; @s zero.  "),
10388           PROMPT_FIX, 0 },
10389
10390         /* Resize_inode not enabled, but resize inode is non-zero */
10391         { PR_0_CLEAR_RESIZE_INODE,
10392           N_("Resize_@i not enabled, but the resize inode is non-zero.  "),
10393           PROMPT_CLEAR, 0 },
10394
10395         /* Resize inode invalid */
10396         { PR_0_RESIZE_INODE_INVALID,
10397           N_("Resize @i not valid.  "),
10398           PROMPT_RECREATE, 0 },
10399
10400         /* Pass 1 errors */
10401
10402         /* Pass 1: Checking inodes, blocks, and sizes */
10403         { PR_1_PASS_HEADER,
10404           N_("Pass 1: Checking @is, @bs, and sizes\n"),
10405           PROMPT_NONE, 0 },
10406
10407         /* Root directory is not an inode */
10408         { PR_1_ROOT_NO_DIR, N_("@r is not a @d.  "),
10409           PROMPT_CLEAR, 0 },
10410
10411         /* Root directory has dtime set */
10412         { PR_1_ROOT_DTIME,
10413           N_("@r has dtime set (probably due to old mke2fs).  "),
10414           PROMPT_FIX, PR_PREEN_OK },
10415
10416         /* Reserved inode has bad mode */
10417         { PR_1_RESERVED_BAD_MODE,
10418           N_("Reserved @i %i %Q has bad mode.  "),
10419           PROMPT_CLEAR, PR_PREEN_OK },
10420
10421         /* Deleted inode has zero dtime */
10422         { PR_1_ZERO_DTIME,
10423           N_("@D @i %i has zero dtime.  "),
10424           PROMPT_FIX, PR_PREEN_OK },
10425
10426         /* Inode in use, but dtime set */
10427         { PR_1_SET_DTIME,
10428           N_("@i %i is in use, but has dtime set.  "),
10429           PROMPT_FIX, PR_PREEN_OK },
10430
10431         /* Zero-length directory */
10432         { PR_1_ZERO_LENGTH_DIR,
10433           N_("@i %i is a @z @d.  "),
10434           PROMPT_CLEAR, PR_PREEN_OK },
10435
10436         /* Block bitmap conflicts with some other fs block */
10437         { PR_1_BB_CONFLICT,
10438           N_("@g %g's @b @B at %b @C.\n"),
10439           PROMPT_RELOCATE, 0 },
10440
10441         /* Inode bitmap conflicts with some other fs block */
10442         { PR_1_IB_CONFLICT,
10443           N_("@g %g's @i @B at %b @C.\n"),
10444           PROMPT_RELOCATE, 0 },
10445
10446         /* Inode table conflicts with some other fs block */
10447         { PR_1_ITABLE_CONFLICT,
10448           N_("@g %g's @i table at %b @C.\n"),
10449           PROMPT_RELOCATE, 0 },
10450
10451         /* Block bitmap is on a bad block */
10452         { PR_1_BB_BAD_BLOCK,
10453           N_("@g %g's @b @B (%b) is bad.  "),
10454           PROMPT_RELOCATE, 0 },
10455
10456         /* Inode bitmap is on a bad block */
10457         { PR_1_IB_BAD_BLOCK,
10458           N_("@g %g's @i @B (%b) is bad.  "),
10459           PROMPT_RELOCATE, 0 },
10460
10461         /* Inode has incorrect i_size */
10462         { PR_1_BAD_I_SIZE,
10463           N_("@i %i, i_size is %Is, @s %N.  "),
10464           PROMPT_FIX, PR_PREEN_OK },
10465
10466         /* Inode has incorrect i_blocks */
10467         { PR_1_BAD_I_BLOCKS,
10468           N_("@i %i, i_@bs is %Ib, @s %N.  "),
10469           PROMPT_FIX, PR_PREEN_OK },
10470
10471         /* Illegal blocknumber in inode */
10472         { PR_1_ILLEGAL_BLOCK_NUM,
10473           N_("@I @b #%B (%b) in @i %i.  "),
10474           PROMPT_CLEAR, PR_LATCH_BLOCK },
10475
10476         /* Block number overlaps fs metadata */
10477         { PR_1_BLOCK_OVERLAPS_METADATA,
10478           N_("@b #%B (%b) overlaps @f metadata in @i %i.  "),
10479           PROMPT_CLEAR, PR_LATCH_BLOCK },
10480
10481         /* Inode has illegal blocks (latch question) */
10482         { PR_1_INODE_BLOCK_LATCH,
10483           N_("@i %i has illegal @b(s).  "),
10484           PROMPT_CLEAR, 0 },
10485
10486         /* Too many bad blocks in inode */
10487         { PR_1_TOO_MANY_BAD_BLOCKS,
10488           N_("Too many illegal @bs in @i %i.\n"),
10489           PROMPT_CLEAR_INODE, PR_NO_OK },
10490
10491         /* Illegal block number in bad block inode */
10492         { PR_1_BB_ILLEGAL_BLOCK_NUM,
10493           N_("@I @b #%B (%b) in bad @b @i.  "),
10494           PROMPT_CLEAR, PR_LATCH_BBLOCK },
10495
10496         /* Bad block inode has illegal blocks (latch question) */
10497         { PR_1_INODE_BBLOCK_LATCH,
10498           N_("Bad @b @i has illegal @b(s).  "),
10499           PROMPT_CLEAR, 0 },
10500
10501         /* Duplicate or bad blocks in use! */
10502         { PR_1_DUP_BLOCKS_PREENSTOP,
10503           N_("Duplicate or bad @b in use!\n"),
10504           PROMPT_NONE, 0 },
10505
10506         /* Bad block used as bad block indirect block */
10507         { PR_1_BBINODE_BAD_METABLOCK,
10508           N_("Bad @b %b used as bad @b @i indirect @b.  "),
10509           PROMPT_CLEAR, PR_LATCH_BBLOCK },
10510
10511         /* Inconsistency can't be fixed prompt */
10512         { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
10513           N_("\nThe bad @b @i has probably been corrupted.  You probably\n"
10514              "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
10515              "in the @f.\n"),
10516           PROMPT_CONTINUE, PR_PREEN_NOMSG },
10517
10518         /* Bad primary block */
10519         { PR_1_BAD_PRIMARY_BLOCK,
10520           N_("\nIf the @b is really bad, the @f can not be fixed.\n"),
10521           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
10522
10523         /* Bad primary block prompt */
10524         { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
10525           N_("You can clear the this @b (and hope for the best) from the\n"
10526           "bad @b list and hope that @b is really OK, but there are no\n"
10527           "guarantees.\n\n"),
10528           PROMPT_CLEAR, PR_PREEN_NOMSG },
10529
10530         /* Bad primary superblock */
10531         { PR_1_BAD_PRIMARY_SUPERBLOCK,
10532           N_("The primary @S (%b) is on the bad @b list.\n"),
10533           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
10534
10535         /* Bad primary block group descriptors */
10536         { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
10537           N_("Block %b in the primary @g descriptors "
10538           "is on the bad @b list\n"),
10539           PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
10540
10541         /* Bad superblock in group */
10542         { PR_1_BAD_SUPERBLOCK,
10543           N_("Warning: Group %g's @S (%b) is bad.\n"),
10544           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
10545
10546         /* Bad block group descriptors in group */
10547         { PR_1_BAD_GROUP_DESCRIPTORS,
10548           N_("Warning: Group %g's copy of the @g descriptors has a bad "
10549           "@b (%b).\n"),
10550           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
10551
10552         /* Block claimed for no reason */
10553         { PR_1_PROGERR_CLAIMED_BLOCK,
10554           N_("Programming error?  @b #%b claimed for no reason in "
10555           "process_bad_@b.\n"),
10556           PROMPT_NONE, PR_PREEN_OK },
10557
10558         /* Error allocating blocks for relocating metadata */
10559         { PR_1_RELOC_BLOCK_ALLOCATE,
10560           N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
10561           PROMPT_NONE, PR_PREEN_OK },
10562
10563         /* Error allocating block buffer during relocation process */
10564         { PR_1_RELOC_MEMORY_ALLOCATE,
10565           N_("@A @b buffer for relocating %s\n"),
10566           PROMPT_NONE, PR_PREEN_OK },
10567
10568         /* Relocating metadata group information from X to Y */
10569         { PR_1_RELOC_FROM_TO,
10570           N_("Relocating @g %g's %s from %b to %c...\n"),
10571           PROMPT_NONE, PR_PREEN_OK },
10572
10573         /* Relocating metatdata group information to X */
10574         { PR_1_RELOC_TO,
10575           N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
10576           PROMPT_NONE, PR_PREEN_OK },
10577
10578         /* Block read error during relocation process */
10579         { PR_1_RELOC_READ_ERR,
10580           N_("Warning: could not read @b %b of %s: %m\n"),
10581           PROMPT_NONE, PR_PREEN_OK },
10582
10583         /* Block write error during relocation process */
10584         { PR_1_RELOC_WRITE_ERR,
10585           N_("Warning: could not write @b %b for %s: %m\n"),
10586           PROMPT_NONE, PR_PREEN_OK },
10587
10588         /* Error allocating inode bitmap */
10589         { PR_1_ALLOCATE_IBITMAP_ERROR,
10590           "@A @i @B (%N): %m\n",
10591           PROMPT_NONE, PR_FATAL },
10592
10593         /* Error allocating block bitmap */
10594         { PR_1_ALLOCATE_BBITMAP_ERROR,
10595           "@A @b @B (%N): %m\n",
10596           PROMPT_NONE, PR_FATAL },
10597
10598         /* Error allocating icount structure */
10599         { PR_1_ALLOCATE_ICOUNT,
10600           N_("@A icount link information: %m\n"),
10601           PROMPT_NONE, PR_FATAL },
10602
10603         /* Error allocating dbcount */
10604         { PR_1_ALLOCATE_DBCOUNT,
10605           N_("@A @d @b array: %m\n"),
10606           PROMPT_NONE, PR_FATAL },
10607
10608         /* Error while scanning inodes */
10609         { PR_1_ISCAN_ERROR,
10610           N_("Error while scanning @is (%i): %m\n"),
10611           PROMPT_NONE, PR_FATAL },
10612
10613         /* Error while iterating over blocks */
10614         { PR_1_BLOCK_ITERATE,
10615           N_("Error while iterating over @bs in @i %i: %m\n"),
10616           PROMPT_NONE, PR_FATAL },
10617
10618         /* Error while storing inode count information */
10619         { PR_1_ICOUNT_STORE,
10620           N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
10621           PROMPT_NONE, PR_FATAL },
10622
10623         /* Error while storing directory block information */
10624         { PR_1_ADD_DBLOCK,
10625           N_("Error storing @d @b information "
10626           "(@i=%i, @b=%b, num=%N): %m\n"),
10627           PROMPT_NONE, PR_FATAL },
10628
10629         /* Error while reading inode (for clearing) */
10630         { PR_1_READ_INODE,
10631           N_("Error reading @i %i: %m\n"),
10632           PROMPT_NONE, PR_FATAL },
10633
10634         /* Suppress messages prompt */
10635         { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
10636
10637         /* Imagic flag set on an inode when filesystem doesn't support it */
10638         { PR_1_SET_IMAGIC,
10639           N_("@i %i has imagic flag set.  "),
10640           PROMPT_CLEAR, 0 },
10641
10642         /* Immutable flag set on a device or socket inode */
10643         { PR_1_SET_IMMUTABLE,
10644           N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
10645              "or append-only flag set.  "),
10646           PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
10647
10648         /* Compression flag set on an inode when filesystem doesn't support it */
10649         { PR_1_COMPR_SET,
10650           N_("@i %i has @cion flag set on @f without @cion support.  "),
10651           PROMPT_CLEAR, 0 },
10652
10653         /* Non-zero size for device, fifo or socket inode */
10654         { PR_1_SET_NONZSIZE,
10655           "Special (@v/socket/fifo) @i %i has non-zero size.  ",
10656           PROMPT_FIX, PR_PREEN_OK },
10657
10658         /* Filesystem revision is 0, but feature flags are set */
10659         { PR_1_FS_REV_LEVEL,
10660           "@f has feature flag(s) set, but is a revision 0 @f.  ",
10661           PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
10662
10663         /* Journal inode is not in use, but contains data */
10664         { PR_1_JOURNAL_INODE_NOT_CLEAR,
10665           "@j @i is not in use, but contains data.  ",
10666           PROMPT_CLEAR, PR_PREEN_OK },
10667
10668         /* Journal has bad mode */
10669         { PR_1_JOURNAL_BAD_MODE,
10670           N_("@j is not regular file.  "),
10671           PROMPT_FIX, PR_PREEN_OK },
10672
10673         /* Deal with inodes that were part of orphan linked list */
10674         { PR_1_LOW_DTIME,
10675           N_("@i %i was part of the orphaned @i list.  "),
10676           PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
10677
10678         /* Deal with inodes that were part of corrupted orphan linked
10679            list (latch question) */
10680         { PR_1_ORPHAN_LIST_REFUGEES,
10681           N_("@is that were part of a corrupted orphan linked list found.  "),
10682           PROMPT_FIX, 0 },
10683
10684         /* Error allocating refcount structure */
10685         { PR_1_ALLOCATE_REFCOUNT,
10686           "@A refcount structure (%N): %m\n",
10687           PROMPT_NONE, PR_FATAL },
10688
10689         /* Error reading extended attribute block */
10690         { PR_1_READ_EA_BLOCK,
10691           N_("Error reading @a @b %b for @i %i.  "),
10692           PROMPT_CLEAR, 0 },
10693
10694         /* Invalid extended attribute block */
10695         { PR_1_BAD_EA_BLOCK,
10696           N_("@i %i has a bad @a @b %b.  "),
10697           PROMPT_CLEAR, 0 },
10698
10699         /* Error reading Extended Attribute block while fixing refcount */
10700         { PR_1_EXTATTR_READ_ABORT,
10701           N_("Error reading @a @b %b (%m).  "),
10702           PROMPT_ABORT, 0 },
10703
10704         /* Extended attribute reference count incorrect */
10705         { PR_1_EXTATTR_REFCOUNT,
10706           N_("@a @b %b has reference count %B, should be %N.  "),
10707           PROMPT_FIX, 0 },
10708
10709         /* Error writing Extended Attribute block while fixing refcount */
10710         { PR_1_EXTATTR_WRITE,
10711           N_("Error writing @a @b %b (%m).  "),
10712           PROMPT_ABORT, 0 },
10713
10714         /* Multiple EA blocks not supported */
10715         { PR_1_EA_MULTI_BLOCK,
10716           N_("@a @b %b has h_blocks > 1.  "),
10717           PROMPT_CLEAR, 0},
10718
10719         /* Error allocating EA region allocation structure */
10720         { PR_1_EA_ALLOC_REGION,
10721           N_("Error allocating @a @b %b.  "),
10722           PROMPT_ABORT, 0},
10723
10724         /* Error EA allocation collision */
10725         { PR_1_EA_ALLOC_COLLISION,
10726           N_("@a @b %b is corrupt (allocation collision).  "),
10727           PROMPT_CLEAR, 0},
10728
10729         /* Bad extended attribute name */
10730         { PR_1_EA_BAD_NAME,
10731           N_("@a @b %b is corrupt (invalid name).  "),
10732           PROMPT_CLEAR, 0},
10733
10734         /* Bad extended attribute value */
10735         { PR_1_EA_BAD_VALUE,
10736           N_("@a @b %b is corrupt (invalid value).  "),
10737           PROMPT_CLEAR, 0},
10738
10739         /* Inode too big (latch question) */
10740         { PR_1_INODE_TOOBIG,
10741           N_("@i %i is too big.  "), PROMPT_TRUNCATE, 0 },
10742
10743         /* Directory too big */
10744         { PR_1_TOOBIG_DIR,
10745           N_("@b #%B (%b) causes @d to be too big.  "),
10746           PROMPT_CLEAR, PR_LATCH_TOOBIG },
10747
10748         /* Regular file too big */
10749         { PR_1_TOOBIG_REG,
10750           N_("@b #%B (%b) causes file to be too big.  "),
10751           PROMPT_CLEAR, PR_LATCH_TOOBIG },
10752
10753         /* Symlink too big */
10754         { PR_1_TOOBIG_SYMLINK,
10755           N_("@b #%B (%b) causes symlink to be too big.  "),
10756           PROMPT_CLEAR, PR_LATCH_TOOBIG },
10757
10758         /* INDEX_FL flag set on a non-HTREE filesystem */
10759         { PR_1_HTREE_SET,
10760           N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
10761           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10762
10763         /* INDEX_FL flag set on a non-directory */
10764         { PR_1_HTREE_NODIR,
10765           N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
10766           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10767
10768         /* Invalid root node in HTREE directory */
10769         { PR_1_HTREE_BADROOT,
10770           N_("@h %i has an invalid root node.\n"),
10771           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10772
10773         /* Unsupported hash version in HTREE directory */
10774         { PR_1_HTREE_HASHV,
10775           N_("@h %i has an unsupported hash version (%N)\n"),
10776           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10777
10778         /* Incompatible flag in HTREE root node */
10779         { PR_1_HTREE_INCOMPAT,
10780           N_("@h %i uses an incompatible htree root node flag.\n"),
10781           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10782
10783         /* HTREE too deep */
10784         { PR_1_HTREE_DEPTH,
10785           N_("@h %i has a tree depth (%N) which is too big\n"),
10786           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
10787
10788         /* Bad block has indirect block that conflicts with filesystem block */
10789         { PR_1_BB_FS_BLOCK,
10790           N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
10791              "@f metadata.  "),
10792           PROMPT_CLEAR, PR_LATCH_BBLOCK },
10793
10794         /* Resize inode failed */
10795         { PR_1_RESIZE_INODE_CREATE,
10796           N_("Resize @i (re)creation failed: %m."),
10797           PROMPT_ABORT, 0 },
10798
10799         /* invalid inode->i_extra_isize */
10800         { PR_1_EXTRA_ISIZE,
10801           N_("@i %i has a extra size (%IS) which is invalid\n"),
10802           PROMPT_FIX, PR_PREEN_OK },
10803
10804         /* invalid ea entry->e_name_len */
10805         { PR_1_ATTR_NAME_LEN,
10806           N_("@a in @i %i has a namelen (%N) which is invalid\n"),
10807           PROMPT_CLEAR, PR_PREEN_OK },
10808
10809         /* invalid ea entry->e_value_size */
10810         { PR_1_ATTR_VALUE_SIZE,
10811           N_("@a in @i %i has a value size (%N) which is invalid\n"),
10812           PROMPT_CLEAR, PR_PREEN_OK },
10813
10814         /* invalid ea entry->e_value_offs */
10815         { PR_1_ATTR_VALUE_OFFSET,
10816           N_("@a in @i %i has a value offset (%N) which is invalid\n"),
10817           PROMPT_CLEAR, PR_PREEN_OK },
10818
10819         /* invalid ea entry->e_value_block */
10820         { PR_1_ATTR_VALUE_BLOCK,
10821           N_("@a in @i %i has a value block (%N) which is invalid (must be 0)\n"),
10822           PROMPT_CLEAR, PR_PREEN_OK },
10823
10824         /* invalid ea entry->e_hash */
10825         { PR_1_ATTR_HASH,
10826           N_("@a in @i %i has a hash (%N) which is invalid (must be 0)\n"),
10827           PROMPT_CLEAR, PR_PREEN_OK },
10828
10829         /* Pass 1b errors */
10830
10831         /* Pass 1B: Rescan for duplicate/bad blocks */
10832         { PR_1B_PASS_HEADER,
10833           N_("Duplicate @bs found... invoking duplicate @b passes.\n"
10834           "Pass 1B: Rescan for duplicate/bad @bs\n"),
10835           PROMPT_NONE, 0 },
10836
10837         /* Duplicate/bad block(s) header */
10838         { PR_1B_DUP_BLOCK_HEADER,
10839           N_("Duplicate/bad @b(s) in @i %i:"),
10840           PROMPT_NONE, 0 },
10841
10842         /* Duplicate/bad block(s) in inode */
10843         { PR_1B_DUP_BLOCK,
10844           " %b",
10845           PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
10846
10847         /* Duplicate/bad block(s) end */
10848         { PR_1B_DUP_BLOCK_END,
10849           "\n",
10850           PROMPT_NONE, PR_PREEN_NOHDR },
10851
10852         /* Error while scanning inodes */
10853         { PR_1B_ISCAN_ERROR,
10854           N_("Error while scanning inodes (%i): %m\n"),
10855           PROMPT_NONE, PR_FATAL },
10856
10857         /* Error allocating inode bitmap */
10858         { PR_1B_ALLOCATE_IBITMAP_ERROR,
10859           N_("@A @i @B (inode_dup_map): %m\n"),
10860           PROMPT_NONE, PR_FATAL },
10861
10862         /* Error while iterating over blocks */
10863         { PR_1B_BLOCK_ITERATE,
10864           N_("Error while iterating over @bs in @i %i (%s): %m\n"),
10865           PROMPT_NONE, 0 },
10866
10867         /* Error adjusting EA refcount */
10868         { PR_1B_ADJ_EA_REFCOUNT,
10869           N_("Error addjusting refcount for @a @b %b (@i %i): %m\n"),
10870           PROMPT_NONE, 0 },
10871
10872
10873         /* Pass 1C: Scan directories for inodes with dup blocks. */
10874         { PR_1C_PASS_HEADER,
10875           N_("Pass 1C: Scan directories for @is with dup @bs.\n"),
10876           PROMPT_NONE, 0 },
10877
10878
10879         /* Pass 1D: Reconciling duplicate blocks */
10880         { PR_1D_PASS_HEADER,
10881           N_("Pass 1D: Reconciling duplicate @bs\n"),
10882           PROMPT_NONE, 0 },
10883
10884         /* File has duplicate blocks */
10885         { PR_1D_DUP_FILE,
10886           N_("File %Q (@i #%i, mod time %IM) \n"
10887           "  has %B duplicate @b(s), shared with %N file(s):\n"),
10888           PROMPT_NONE, 0 },
10889
10890         /* List of files sharing duplicate blocks */
10891         { PR_1D_DUP_FILE_LIST,
10892           N_("\t%Q (@i #%i, mod time %IM)\n"),
10893           PROMPT_NONE, 0 },
10894
10895         /* File sharing blocks with filesystem metadata  */
10896         { PR_1D_SHARE_METADATA,
10897           N_("\t<@f metadata>\n"),
10898           PROMPT_NONE, 0 },
10899
10900         /* Report of how many duplicate/bad inodes */
10901         { PR_1D_NUM_DUP_INODES,
10902           N_("(There are %N @is containing duplicate/bad @bs.)\n\n"),
10903           PROMPT_NONE, 0 },
10904
10905         /* Duplicated blocks already reassigned or cloned. */
10906         { PR_1D_DUP_BLOCKS_DEALT,
10907           N_("Duplicated @bs already reassigned or cloned.\n\n"),
10908           PROMPT_NONE, 0 },
10909
10910         /* Clone duplicate/bad blocks? */
10911         { PR_1D_CLONE_QUESTION,
10912           "", PROMPT_CLONE, PR_NO_OK },
10913
10914         /* Delete file? */
10915         { PR_1D_DELETE_QUESTION,
10916           "", PROMPT_DELETE, 0 },
10917
10918         /* Couldn't clone file (error) */
10919         { PR_1D_CLONE_ERROR,
10920           N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
10921
10922         /* Pass 2 errors */
10923
10924         /* Pass 2: Checking directory structure */
10925         { PR_2_PASS_HEADER,
10926           N_("Pass 2: Checking @d structure\n"),
10927           PROMPT_NONE, 0 },
10928
10929         /* Bad inode number for '.' */
10930         { PR_2_BAD_INODE_DOT,
10931           N_("Bad @i number for '.' in @d @i %i.\n"),
10932           PROMPT_FIX, 0 },
10933
10934         /* Directory entry has bad inode number */
10935         { PR_2_BAD_INO,
10936           N_("@E has bad @i #: %Di.\n"),
10937           PROMPT_CLEAR, 0 },
10938
10939         /* Directory entry has deleted or unused inode */
10940         { PR_2_UNUSED_INODE,
10941           N_("@E has @D/unused @i %Di.  "),
10942           PROMPT_CLEAR, PR_PREEN_OK },
10943
10944         /* Directry entry is link to '.' */
10945         { PR_2_LINK_DOT,
10946           N_("@E @L to '.'  "),
10947           PROMPT_CLEAR, 0 },
10948
10949         /* Directory entry points to inode now located in a bad block */
10950         { PR_2_BB_INODE,
10951           N_("@E points to @i (%Di) located in a bad @b.\n"),
10952           PROMPT_CLEAR, 0 },
10953
10954         /* Directory entry contains a link to a directory */
10955         { PR_2_LINK_DIR,
10956           N_("@E @L to @d %P (%Di).\n"),
10957           PROMPT_CLEAR, 0 },
10958
10959         /* Directory entry contains a link to the root directry */
10960         { PR_2_LINK_ROOT,
10961           N_("@E @L to the @r.\n"),
10962           PROMPT_CLEAR, 0 },
10963
10964         /* Directory entry has illegal characters in its name */
10965         { PR_2_BAD_NAME,
10966           N_("@E has illegal characters in its name.\n"),
10967           PROMPT_FIX, 0 },
10968
10969         /* Missing '.' in directory inode */
10970         { PR_2_MISSING_DOT,
10971           N_("Missing '.' in @d @i %i.\n"),
10972           PROMPT_FIX, 0 },
10973
10974         /* Missing '..' in directory inode */
10975         { PR_2_MISSING_DOT_DOT,
10976           N_("Missing '..' in @d @i %i.\n"),
10977           PROMPT_FIX, 0 },
10978
10979         /* First entry in directory inode doesn't contain '.' */
10980         { PR_2_1ST_NOT_DOT,
10981           N_("First @e '%Dn' (inode=%Di) in @d @i %i (%p) @s '.'\n"),
10982           PROMPT_FIX, 0 },
10983
10984         /* Second entry in directory inode doesn't contain '..' */
10985         { PR_2_2ND_NOT_DOT_DOT,
10986           N_("Second @e '%Dn' (inode=%Di) in @d @i %i @s '..'\n"),
10987           PROMPT_FIX, 0 },
10988
10989         /* i_faddr should be zero */
10990         { PR_2_FADDR_ZERO,
10991           N_("i_faddr @F %IF, @s zero.\n"),
10992           PROMPT_CLEAR, 0 },
10993
10994         /* i_file_acl should be zero */
10995         { PR_2_FILE_ACL_ZERO,
10996           N_("i_file_acl @F %If, @s zero.\n"),
10997           PROMPT_CLEAR, 0 },
10998
10999         /* i_dir_acl should be zero */
11000         { PR_2_DIR_ACL_ZERO,
11001           N_("i_dir_acl @F %Id, @s zero.\n"),
11002           PROMPT_CLEAR, 0 },
11003
11004         /* i_frag should be zero */
11005         { PR_2_FRAG_ZERO,
11006           N_("i_frag @F %N, @s zero.\n"),
11007           PROMPT_CLEAR, 0 },
11008
11009         /* i_fsize should be zero */
11010         { PR_2_FSIZE_ZERO,
11011           N_("i_fsize @F %N, @s zero.\n"),
11012           PROMPT_CLEAR, 0 },
11013
11014         /* inode has bad mode */
11015         { PR_2_BAD_MODE,
11016           N_("@i %i (%Q) has a bad mode (%Im).\n"),
11017           PROMPT_CLEAR, 0 },
11018
11019         /* directory corrupted */
11020         { PR_2_DIR_CORRUPTED,
11021           N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
11022           PROMPT_SALVAGE, 0 },
11023
11024         /* filename too long */
11025         { PR_2_FILENAME_LONG,
11026           N_("@d @i %i, @b %B, offset %N: filename too long\n"),
11027           PROMPT_TRUNCATE, 0 },
11028
11029         /* Directory inode has a missing block (hole) */
11030         { PR_2_DIRECTORY_HOLE,
11031           N_("@d @i %i has an unallocated @b #%B.  "),
11032           PROMPT_ALLOCATE, 0 },
11033
11034         /* '.' is not NULL terminated */
11035         { PR_2_DOT_NULL_TERM,
11036           N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
11037           PROMPT_FIX, 0 },
11038
11039         /* '..' is not NULL terminated */
11040         { PR_2_DOT_DOT_NULL_TERM,
11041           N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
11042           PROMPT_FIX, 0 },
11043
11044         /* Illegal character device inode */
11045         { PR_2_BAD_CHAR_DEV,
11046           N_("@i %i (%Q) is an @I character @v.\n"),
11047           PROMPT_CLEAR, 0 },
11048
11049         /* Illegal block device inode */
11050         { PR_2_BAD_BLOCK_DEV,
11051           N_("@i %i (%Q) is an @I @b @v.\n"),
11052           PROMPT_CLEAR, 0 },
11053
11054         /* Duplicate '.' entry */
11055         { PR_2_DUP_DOT,
11056           N_("@E is duplicate '.' @e.\n"),
11057           PROMPT_FIX, 0 },
11058
11059         /* Duplicate '..' entry */
11060         { PR_2_DUP_DOT_DOT,
11061           N_("@E is duplicate '..' @e.\n"),
11062           PROMPT_FIX, 0 },
11063
11064         /* Internal error: couldn't find dir_info */
11065         { PR_2_NO_DIRINFO,
11066           N_("Internal error: couldn't find dir_info for %i.\n"),
11067           PROMPT_NONE, PR_FATAL },
11068
11069         /* Final rec_len is wrong */
11070         { PR_2_FINAL_RECLEN,
11071           N_("@E has rec_len of %Dr, should be %N.\n"),
11072           PROMPT_FIX, 0 },
11073
11074         /* Error allocating icount structure */
11075         { PR_2_ALLOCATE_ICOUNT,
11076           N_("@A icount structure: %m\n"),
11077           PROMPT_NONE, PR_FATAL },
11078
11079         /* Error iterating over directory blocks */
11080         { PR_2_DBLIST_ITERATE,
11081           N_("Error iterating over @d @bs: %m\n"),
11082           PROMPT_NONE, PR_FATAL },
11083
11084         /* Error reading directory block */
11085         { PR_2_READ_DIRBLOCK,
11086           N_("Error reading @d @b %b (@i %i): %m\n"),
11087           PROMPT_CONTINUE, 0 },
11088
11089         /* Error writing directory block */
11090         { PR_2_WRITE_DIRBLOCK,
11091           N_("Error writing @d @b %b (@i %i): %m\n"),
11092           PROMPT_CONTINUE, 0 },
11093
11094         /* Error allocating new directory block */
11095         { PR_2_ALLOC_DIRBOCK,
11096           N_("@A new @d @b for @i %i (%s): %m\n"),
11097           PROMPT_NONE, 0 },
11098
11099         /* Error deallocating inode */
11100         { PR_2_DEALLOC_INODE,
11101           N_("Error deallocating @i %i: %m\n"),
11102           PROMPT_NONE, PR_FATAL },
11103
11104         /* Directory entry for '.' is big.  Split? */
11105         { PR_2_SPLIT_DOT,
11106           N_("@d @e for '.' is big.  "),
11107           PROMPT_SPLIT, PR_NO_OK },
11108
11109         /* Illegal FIFO inode */
11110         { PR_2_BAD_FIFO,
11111           N_("@i %i (%Q) is an @I FIFO.\n"),
11112           PROMPT_CLEAR, 0 },
11113
11114         /* Illegal socket inode */
11115         { PR_2_BAD_SOCKET,
11116           N_("@i %i (%Q) is an @I socket.\n"),
11117           PROMPT_CLEAR, 0 },
11118
11119         /* Directory filetype not set */
11120         { PR_2_SET_FILETYPE,
11121           N_("Setting filetype for @E to %N.\n"),
11122           PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
11123
11124         /* Directory filetype incorrect */
11125         { PR_2_BAD_FILETYPE,
11126           N_("@E has an incorrect filetype (was %Dt, should be %N).\n"),
11127           PROMPT_FIX, 0 },
11128
11129         /* Directory filetype set on filesystem */
11130         { PR_2_CLEAR_FILETYPE,
11131           N_("@E has filetype set.\n"),
11132           PROMPT_CLEAR, PR_PREEN_OK },
11133
11134         /* Directory filename is null */
11135         { PR_2_NULL_NAME,
11136           N_("@E has a zero-length name.\n"),
11137           PROMPT_CLEAR, 0 },
11138
11139         /* Invalid symlink */
11140         { PR_2_INVALID_SYMLINK,
11141           N_("Symlink %Q (@i #%i) is invalid.\n"),
11142           PROMPT_CLEAR, 0 },
11143
11144         /* i_file_acl (extended attribute block) is bad */
11145         { PR_2_FILE_ACL_BAD,
11146           N_("@a @b @F invalid (%If).\n"),
11147           PROMPT_CLEAR, 0 },
11148
11149         /* Filesystem contains large files, but has no such flag in sb */
11150         { PR_2_FEATURE_LARGE_FILES,
11151           N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
11152           PROMPT_FIX, 0 },
11153
11154         /* Node in HTREE directory not referenced */
11155         { PR_2_HTREE_NOTREF,
11156           N_("@p @h %d: node (%B) not referenced\n"),
11157           PROMPT_NONE, 0 },
11158
11159         /* Node in HTREE directory referenced twice */
11160         { PR_2_HTREE_DUPREF,
11161           N_("@p @h %d: node (%B) referenced twice\n"),
11162           PROMPT_NONE, 0 },
11163
11164         /* Node in HTREE directory has bad min hash */
11165         { PR_2_HTREE_MIN_HASH,
11166           N_("@p @h %d: node (%B) has bad min hash\n"),
11167           PROMPT_NONE, 0 },
11168
11169         /* Node in HTREE directory has bad max hash */
11170         { PR_2_HTREE_MAX_HASH,
11171           N_("@p @h %d: node (%B) has bad max hash\n"),
11172           PROMPT_NONE, 0 },
11173
11174         /* Clear invalid HTREE directory */
11175         { PR_2_HTREE_CLEAR,
11176           N_("Invalid @h %d (%q).  "), PROMPT_CLEAR, 0 },
11177
11178         /* Bad block in htree interior node */
11179         { PR_2_HTREE_BADBLK,
11180           N_("@p @h %d (%q): bad @b number %b.\n"),
11181           PROMPT_CLEAR_HTREE, 0 },
11182
11183         /* Error adjusting EA refcount */
11184         { PR_2_ADJ_EA_REFCOUNT,
11185           N_("Error addjusting refcount for @a @b %b (@i %i): %m\n"),
11186           PROMPT_NONE, PR_FATAL },
11187
11188         /* Invalid HTREE root node */
11189         { PR_2_HTREE_BAD_ROOT,
11190           N_("@p @h %d: root node is invalid\n"),
11191           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11192
11193         /* Invalid HTREE limit */
11194         { PR_2_HTREE_BAD_LIMIT,
11195           N_("@p @h %d: node (%B) has bad limit (%N)\n"),
11196           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11197
11198         /* Invalid HTREE count */
11199         { PR_2_HTREE_BAD_COUNT,
11200           N_("@p @h %d: node (%B) has bad count (%N)\n"),
11201           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11202
11203         /* HTREE interior node has out-of-order hashes in table */
11204         { PR_2_HTREE_HASH_ORDER,
11205           N_("@p @h %d: node (%B) has an unordered hash table\n"),
11206           PROMPT_CLEAR_HTREE, PR_PREEN_OK },
11207
11208         /* Node in HTREE directory has bad depth */
11209         { PR_2_HTREE_BAD_DEPTH,
11210           N_("@p @h %d: node (%B) has bad depth\n"),
11211           PROMPT_NONE, 0 },
11212
11213         /* Duplicate directory entry found */
11214         { PR_2_DUPLICATE_DIRENT,
11215           N_("Duplicate @E found.  "),
11216           PROMPT_CLEAR, 0 },
11217
11218         /* Non-unique filename found */
11219         { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
11220           N_("@E has a non-unique filename.\nRename to %s"),
11221           PROMPT_NULL, 0 },
11222
11223         /* Duplicate directory entry found */
11224         { PR_2_REPORT_DUP_DIRENT,
11225           N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
11226           PROMPT_NONE, 0 },
11227
11228         /* Pass 3 errors */
11229
11230         /* Pass 3: Checking directory connectivity */
11231         { PR_3_PASS_HEADER,
11232           N_("Pass 3: Checking @d connectivity\n"),
11233           PROMPT_NONE, 0 },
11234
11235         /* Root inode not allocated */
11236         { PR_3_NO_ROOT_INODE,
11237           N_("@r not allocated.  "),
11238           PROMPT_ALLOCATE, 0 },
11239
11240         /* No room in lost+found */
11241         { PR_3_EXPAND_LF_DIR,
11242           N_("No room in @l @d.  "),
11243           PROMPT_EXPAND, 0 },
11244
11245         /* Unconnected directory inode */
11246         { PR_3_UNCONNECTED_DIR,
11247           N_("Unconnected @d @i %i (%p)\n"),
11248           PROMPT_CONNECT, 0 },
11249
11250         /* /lost+found not found */
11251         { PR_3_NO_LF_DIR,
11252           N_("/@l not found.  "),
11253           PROMPT_CREATE, PR_PREEN_OK },
11254
11255         /* .. entry is incorrect */
11256         { PR_3_BAD_DOT_DOT,
11257           N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
11258           PROMPT_FIX, 0 },
11259
11260         /* Bad or non-existent /lost+found.  Cannot reconnect */
11261         { PR_3_NO_LPF,
11262           N_("Bad or non-existent /@l.  Cannot reconnect.\n"),
11263           PROMPT_NONE, 0 },
11264
11265         /* Could not expand /lost+found */
11266         { PR_3_CANT_EXPAND_LPF,
11267           N_("Could not expand /@l: %m\n"),
11268           PROMPT_NONE, 0 },
11269
11270         /* Could not reconnect inode */
11271         { PR_3_CANT_RECONNECT,
11272           N_("Could not reconnect %i: %m\n"),
11273           PROMPT_NONE, 0 },
11274
11275         /* Error while trying to find /lost+found */
11276         { PR_3_ERR_FIND_LPF,
11277           N_("Error while trying to find /@l: %m\n"),
11278           PROMPT_NONE, 0 },
11279
11280         /* Error in ext2fs_new_block while creating /lost+found */
11281         { PR_3_ERR_LPF_NEW_BLOCK,
11282           N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
11283           PROMPT_NONE, 0 },
11284
11285         /* Error in ext2fs_new_inode while creating /lost+found */
11286         { PR_3_ERR_LPF_NEW_INODE,
11287           N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
11288           PROMPT_NONE, 0 },
11289
11290         /* Error in ext2fs_new_dir_block while creating /lost+found */
11291         { PR_3_ERR_LPF_NEW_DIR_BLOCK,
11292           N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
11293           PROMPT_NONE, 0 },
11294
11295         /* Error while writing directory block for /lost+found */
11296         { PR_3_ERR_LPF_WRITE_BLOCK,
11297           N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
11298           PROMPT_NONE, 0 },
11299
11300         /* Error while adjusting inode count */
11301         { PR_3_ADJUST_INODE,
11302           N_("Error while adjusting @i count on @i %i\n"),
11303           PROMPT_NONE, 0 },
11304
11305         /* Couldn't fix parent directory -- error */
11306         { PR_3_FIX_PARENT_ERR,
11307           N_("Couldn't fix parent of @i %i: %m\n\n"),
11308           PROMPT_NONE, 0 },
11309
11310         /* Couldn't fix parent directory -- couldn't find it */
11311         { PR_3_FIX_PARENT_NOFIND,
11312           N_("Couldn't fix parent of @i %i: Couldn't find parent @d entry\n\n"),
11313           PROMPT_NONE, 0 },
11314
11315         /* Error allocating inode bitmap */
11316         { PR_3_ALLOCATE_IBITMAP_ERROR,
11317           N_("@A @i @B (%N): %m\n"),
11318           PROMPT_NONE, PR_FATAL },
11319
11320         /* Error creating root directory */
11321         { PR_3_CREATE_ROOT_ERROR,
11322           N_("Error creating root @d (%s): %m\n"),
11323           PROMPT_NONE, PR_FATAL },
11324
11325         /* Error creating lost and found directory */
11326         { PR_3_CREATE_LPF_ERROR,
11327           N_("Error creating /@l @d (%s): %m\n"),
11328           PROMPT_NONE, PR_FATAL },
11329
11330         /* Root inode is not directory; aborting */
11331         { PR_3_ROOT_NOT_DIR_ABORT,
11332           N_("@r is not a @d; aborting.\n"),
11333           PROMPT_NONE, PR_FATAL },
11334
11335         /* Cannot proceed without a root inode. */
11336         { PR_3_NO_ROOT_INODE_ABORT,
11337           N_("Cannot proceed without a @r.\n"),
11338           PROMPT_NONE, PR_FATAL },
11339
11340         /* Internal error: couldn't find dir_info */
11341         { PR_3_NO_DIRINFO,
11342           N_("Internal error: couldn't find dir_info for %i.\n"),
11343           PROMPT_NONE, PR_FATAL },
11344
11345         /* Lost+found not a directory */
11346         { PR_3_LPF_NOTDIR,
11347           N_("/@l is not a @d (ino=%i)\n"),
11348           PROMPT_UNLINK, 0 },
11349
11350         /* Pass 3A Directory Optimization       */
11351
11352         /* Pass 3A: Optimizing directories */
11353         { PR_3A_PASS_HEADER,
11354           N_("Pass 3A: Optimizing directories\n"),
11355           PROMPT_NONE, PR_PREEN_NOMSG },
11356
11357         /* Error iterating over directories */
11358         { PR_3A_OPTIMIZE_ITER,
11359           N_("Failed to create dirs_to_hash iterator: %m"),
11360           PROMPT_NONE, 0 },
11361
11362         /* Error rehash directory */
11363         { PR_3A_OPTIMIZE_DIR_ERR,
11364           N_("Failed to optimize directory %q (%d): %m"),
11365           PROMPT_NONE, 0 },
11366
11367         /* Rehashing dir header */
11368         { PR_3A_OPTIMIZE_DIR_HEADER,
11369           N_("Optimizing directories: "),
11370           PROMPT_NONE, PR_MSG_ONLY },
11371
11372         /* Rehashing directory %d */
11373         { PR_3A_OPTIMIZE_DIR,
11374           " %d",
11375           PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
11376
11377         /* Rehashing dir end */
11378         { PR_3A_OPTIMIZE_DIR_END,
11379           "\n",
11380           PROMPT_NONE, PR_PREEN_NOHDR },
11381
11382         /* Pass 4 errors */
11383
11384         /* Pass 4: Checking reference counts */
11385         { PR_4_PASS_HEADER,
11386           N_("Pass 4: Checking reference counts\n"),
11387           PROMPT_NONE, 0 },
11388
11389         /* Unattached zero-length inode */
11390         { PR_4_ZERO_LEN_INODE,
11391           "@u @z @i %i.  ",
11392           PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
11393
11394         /* Unattached inode */
11395         { PR_4_UNATTACHED_INODE,
11396           "@u @i %i\n",
11397           PROMPT_CONNECT, 0 },
11398
11399         /* Inode ref count wrong */
11400         { PR_4_BAD_REF_COUNT,
11401           N_("@i %i ref count is %Il, @s %N.  "),
11402           PROMPT_FIX, PR_PREEN_OK },
11403
11404         { PR_4_INCONSISTENT_COUNT,
11405           N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
11406           "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
11407           "@i_link_info[%i] is %N, @i.i_links_count is %Il.  "
11408           "They should be the same!\n"),
11409           PROMPT_NONE, 0 },
11410
11411         /* Pass 5 errors */
11412
11413         /* Pass 5: Checking group summary information */
11414         { PR_5_PASS_HEADER,
11415           N_("Pass 5: Checking @g summary information\n"),
11416           PROMPT_NONE, 0 },
11417
11418         /* Padding at end of inode bitmap is not set. */
11419         { PR_5_INODE_BMAP_PADDING,
11420           N_("Padding at end of @i @B is not set. "),
11421           PROMPT_FIX, PR_PREEN_OK },
11422
11423         /* Padding at end of block bitmap is not set. */
11424         { PR_5_BLOCK_BMAP_PADDING,
11425           N_("Padding at end of @b @B is not set. "),
11426           PROMPT_FIX, PR_PREEN_OK },
11427
11428         /* Block bitmap differences header */
11429         { PR_5_BLOCK_BITMAP_HEADER,
11430           N_("@b @B differences: "),
11431           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
11432
11433         /* Block not used, but marked in bitmap */
11434         { PR_5_BLOCK_UNUSED,
11435           " -%b",
11436           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11437
11438         /* Block used, but not marked used in bitmap */
11439         { PR_5_BLOCK_USED,
11440           " +%b",
11441           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11442
11443         /* Block bitmap differences end */
11444         { PR_5_BLOCK_BITMAP_END,
11445           "\n",
11446           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11447
11448         /* Inode bitmap differences header */
11449         { PR_5_INODE_BITMAP_HEADER,
11450           N_("@i @B differences: "),
11451           PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
11452
11453         /* Inode not used, but marked in bitmap */
11454         { PR_5_INODE_UNUSED,
11455           " -%i",
11456           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11457
11458         /* Inode used, but not marked used in bitmap */
11459         { PR_5_INODE_USED,
11460           " +%i",
11461           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11462
11463         /* Inode bitmap differences end */
11464         { PR_5_INODE_BITMAP_END,
11465           "\n",
11466           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11467
11468         /* Free inodes count for group wrong */
11469         { PR_5_FREE_INODE_COUNT_GROUP,
11470           N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
11471           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11472
11473         /* Directories count for group wrong */
11474         { PR_5_FREE_DIR_COUNT_GROUP,
11475           N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
11476           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11477
11478         /* Free inodes count wrong */
11479         { PR_5_FREE_INODE_COUNT,
11480           N_("Free @is count wrong (%i, counted=%j).\n"),
11481           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11482
11483         /* Free blocks count for group wrong */
11484         { PR_5_FREE_BLOCK_COUNT_GROUP,
11485           N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
11486           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11487
11488         /* Free blocks count wrong */
11489         { PR_5_FREE_BLOCK_COUNT,
11490           N_("Free @bs count wrong (%b, counted=%c).\n"),
11491           PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
11492
11493         /* Programming error: bitmap endpoints don't match */
11494         { PR_5_BMAP_ENDPOINTS,
11495           N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
11496           "match calculated @B endpoints (%i, %j)\n"),
11497           PROMPT_NONE, PR_FATAL },
11498
11499         /* Internal error: fudging end of bitmap */
11500         { PR_5_FUDGE_BITMAP_ERROR,
11501           N_("Internal error: fudging end of bitmap (%N)\n"),
11502           PROMPT_NONE, PR_FATAL },
11503
11504         /* Error copying in replacement inode bitmap */
11505         { PR_5_COPY_IBITMAP_ERROR,
11506           "Error copying in replacement @i @B: %m\n",
11507           PROMPT_NONE, PR_FATAL },
11508
11509         /* Error copying in replacement block bitmap */
11510         { PR_5_COPY_BBITMAP_ERROR,
11511           "Error copying in replacement @b @B: %m\n",
11512           PROMPT_NONE, PR_FATAL },
11513
11514         /* Block range not used, but marked in bitmap */
11515         { PR_5_BLOCK_RANGE_UNUSED,
11516           " -(%b--%c)",
11517           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11518
11519         /* Block range used, but not marked used in bitmap */
11520         { PR_5_BLOCK_RANGE_USED,
11521           " +(%b--%c)",
11522           PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11523
11524         /* Inode range not used, but marked in bitmap */
11525         { PR_5_INODE_RANGE_UNUSED,
11526           " -(%i--%j)",
11527           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11528
11529         /* Inode range used, but not marked used in bitmap */
11530         { PR_5_INODE_RANGE_USED,
11531           " +(%i--%j)",
11532           PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
11533
11534         { 0 }
11535 };
11536
11537 /*
11538  * This is the latch flags register.  It allows several problems to be
11539  * "latched" together.  This means that the user has to answer but one
11540  * question for the set of problems, and all of the associated
11541  * problems will be either fixed or not fixed.
11542  */
11543 static struct latch_descr pr_latch_info[] = {
11544         { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
11545         { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
11546         { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
11547         { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
11548         { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
11549         { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
11550         { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
11551         { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
11552         { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
11553         { -1, 0, 0 },
11554 };
11555
11556 static const struct e2fsck_problem *find_problem(problem_t code)
11557 {
11558         int     i;
11559
11560         for (i=0; problem_table[i].e2p_code; i++) {
11561                 if (problem_table[i].e2p_code == code)
11562                         return &problem_table[i];
11563         }
11564         return 0;
11565 }
11566
11567 static struct latch_descr *find_latch(int code)
11568 {
11569         int     i;
11570
11571         for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
11572                 if (pr_latch_info[i].latch_code == code)
11573                         return &pr_latch_info[i];
11574         }
11575         return 0;
11576 }
11577
11578 int end_problem_latch(e2fsck_t ctx, int mask)
11579 {
11580         struct latch_descr *ldesc;
11581         struct problem_context pctx;
11582         int answer = -1;
11583
11584         ldesc = find_latch(mask);
11585         if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
11586                 clear_problem_context(&pctx);
11587                 answer = fix_problem(ctx, ldesc->end_message, &pctx);
11588         }
11589         ldesc->flags &= ~(PRL_VARIABLE);
11590         return answer;
11591 }
11592
11593 int set_latch_flags(int mask, int setflags, int clearflags)
11594 {
11595         struct latch_descr *ldesc;
11596
11597         ldesc = find_latch(mask);
11598         if (!ldesc)
11599                 return -1;
11600         ldesc->flags |= setflags;
11601         ldesc->flags &= ~clearflags;
11602         return 0;
11603 }
11604
11605 void clear_problem_context(struct problem_context *ctx)
11606 {
11607         memset(ctx, 0, sizeof(struct problem_context));
11608         ctx->blkcount = -1;
11609         ctx->group = -1;
11610 }
11611
11612 int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
11613 {
11614         ext2_filsys fs = ctx->fs;
11615         const struct e2fsck_problem *ptr;
11616         struct latch_descr *ldesc = 0;
11617         const char *message;
11618         int             def_yn, answer, ans;
11619         int             print_answer = 0;
11620         int             suppress = 0;
11621
11622         ptr = find_problem(code);
11623         if (!ptr) {
11624                 printf(_("Unhandled error code (0x%x)!\n"), code);
11625                 return 0;
11626         }
11627         def_yn = 1;
11628         if ((ptr->flags & PR_NO_DEFAULT) ||
11629             ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
11630             (ctx->options & E2F_OPT_NO))
11631                 def_yn= 0;
11632
11633         /*
11634          * Do special latch processing.  This is where we ask the
11635          * latch question, if it exists
11636          */
11637         if (ptr->flags & PR_LATCH_MASK) {
11638                 ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
11639                 if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
11640                         ans = fix_problem(ctx, ldesc->question, pctx);
11641                         if (ans == 1)
11642                                 ldesc->flags |= PRL_YES;
11643                         if (ans == 0)
11644                                 ldesc->flags |= PRL_NO;
11645                         ldesc->flags |= PRL_LATCHED;
11646                 }
11647                 if (ldesc->flags & PRL_SUPPRESS)
11648                         suppress++;
11649         }
11650         if ((ptr->flags & PR_PREEN_NOMSG) &&
11651             (ctx->options & E2F_OPT_PREEN))
11652                 suppress++;
11653         if ((ptr->flags & PR_NO_NOMSG) &&
11654             (ctx->options & E2F_OPT_NO))
11655                 suppress++;
11656         if (!suppress) {
11657                 message = ptr->e2p_description;
11658                 if ((ctx->options & E2F_OPT_PREEN) &&
11659                     !(ptr->flags & PR_PREEN_NOHDR)) {
11660                         printf("%s: ", ctx->device_name ?
11661                                ctx->device_name : ctx->filesystem_name);
11662                 }
11663                 if (*message)
11664                         print_e2fsck_message(ctx, _(message), pctx, 1);
11665         }
11666         if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
11667                 preenhalt(ctx);
11668
11669         if (ptr->flags & PR_FATAL)
11670                 fatal_error(ctx, 0);
11671
11672         if (ptr->prompt == PROMPT_NONE) {
11673                 if (ptr->flags & PR_NOCOLLATE)
11674                         answer = -1;
11675                 else
11676                         answer = def_yn;
11677         } else {
11678                 if (ctx->options & E2F_OPT_PREEN) {
11679                         answer = def_yn;
11680                         if (!(ptr->flags & PR_PREEN_NOMSG))
11681                                 print_answer = 1;
11682                 } else if ((ptr->flags & PR_LATCH_MASK) &&
11683                            (ldesc->flags & (PRL_YES | PRL_NO))) {
11684                         if (!suppress)
11685                                 print_answer = 1;
11686                         if (ldesc->flags & PRL_YES)
11687                                 answer = 1;
11688                         else
11689                                 answer = 0;
11690                 } else
11691                         answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
11692                 if (!answer && !(ptr->flags & PR_NO_OK))
11693                         ext2fs_unmark_valid(fs);
11694
11695                 if (print_answer)
11696                         printf("%s.\n", answer ?
11697                                _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
11698
11699         }
11700
11701         if ((ptr->prompt == PROMPT_ABORT) && answer)
11702                 fatal_error(ctx, 0);
11703
11704         if (ptr->flags & PR_AFTER_CODE)
11705                 answer = fix_problem(ctx, ptr->second_code, pctx);
11706
11707         return answer;
11708 }
11709
11710 /*
11711  * linux/fs/recovery.c
11712  *
11713  * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
11714  */
11715
11716 /*
11717  * Maintain information about the progress of the recovery job, so that
11718  * the different passes can carry information between them.
11719  */
11720 struct recovery_info
11721 {
11722         tid_t           start_transaction;
11723         tid_t           end_transaction;
11724
11725         int             nr_replays;
11726         int             nr_revokes;
11727         int             nr_revoke_hits;
11728 };
11729
11730 enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
11731 static int do_one_pass(journal_t *journal,
11732                                 struct recovery_info *info, enum passtype pass);
11733 static int scan_revoke_records(journal_t *, struct buffer_head *,
11734                                 tid_t, struct recovery_info *);
11735
11736 /*
11737  * Read a block from the journal
11738  */
11739
11740 static int jread(struct buffer_head **bhp, journal_t *journal,
11741                  unsigned int offset)
11742 {
11743         int err;
11744         unsigned long blocknr;
11745         struct buffer_head *bh;
11746
11747         *bhp = NULL;
11748
11749         J_ASSERT (offset < journal->j_maxlen);
11750
11751         err = journal_bmap(journal, offset, &blocknr);
11752
11753         if (err) {
11754                 printk (KERN_ERR "JBD: bad block at offset %u\n",
11755                         offset);
11756                 return err;
11757         }
11758
11759         bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
11760         if (!bh)
11761                 return -ENOMEM;
11762
11763         if (!buffer_uptodate(bh)) {
11764                 /* If this is a brand new buffer, start readahead.
11765                    Otherwise, we assume we are already reading it.  */
11766                 if (!buffer_req(bh))
11767                         do_readahead(journal, offset);
11768                 wait_on_buffer(bh);
11769         }
11770
11771         if (!buffer_uptodate(bh)) {
11772                 printk (KERN_ERR "JBD: Failed to read block at offset %u\n",
11773                         offset);
11774                 brelse(bh);
11775                 return -EIO;
11776         }
11777
11778         *bhp = bh;
11779         return 0;
11780 }
11781
11782
11783 /*
11784  * Count the number of in-use tags in a journal descriptor block.
11785  */
11786
11787 static int count_tags(struct buffer_head *bh, int size)
11788 {
11789         char *                  tagp;
11790         journal_block_tag_t *   tag;
11791         int                     nr = 0;
11792
11793         tagp = &bh->b_data[sizeof(journal_header_t)];
11794
11795         while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
11796                 tag = (journal_block_tag_t *) tagp;
11797
11798                 nr++;
11799                 tagp += sizeof(journal_block_tag_t);
11800                 if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
11801                         tagp += 16;
11802
11803                 if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
11804                         break;
11805         }
11806
11807         return nr;
11808 }
11809
11810
11811 /* Make sure we wrap around the log correctly! */
11812 #define wrap(journal, var)                                              \
11813 do {                                                                    \
11814         if (var >= (journal)->j_last)                                   \
11815                 var -= ((journal)->j_last - (journal)->j_first);        \
11816 } while (0)
11817
11818 /**
11819  * int journal_recover(journal_t *journal) - recovers a on-disk journal
11820  * @journal: the journal to recover
11821  *
11822  * The primary function for recovering the log contents when mounting a
11823  * journaled device.
11824  *
11825  * Recovery is done in three passes.  In the first pass, we look for the
11826  * end of the log.  In the second, we assemble the list of revoke
11827  * blocks.  In the third and final pass, we replay any un-revoked blocks
11828  * in the log.
11829  */
11830 int journal_recover(journal_t *journal)
11831 {
11832         int                     err;
11833         journal_superblock_t *  sb;
11834
11835         struct recovery_info    info;
11836
11837         memset(&info, 0, sizeof(info));
11838         sb = journal->j_superblock;
11839
11840         /*
11841          * The journal superblock's s_start field (the current log head)
11842          * is always zero if, and only if, the journal was cleanly
11843          * unmounted.
11844          */
11845
11846         if (!sb->s_start) {
11847                 jbd_debug(1, "No recovery required, last transaction %d\n",
11848                           ntohl(sb->s_sequence));
11849                 journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
11850                 return 0;
11851         }
11852
11853         err = do_one_pass(journal, &info, PASS_SCAN);
11854         if (!err)
11855                 err = do_one_pass(journal, &info, PASS_REVOKE);
11856         if (!err)
11857                 err = do_one_pass(journal, &info, PASS_REPLAY);
11858
11859         jbd_debug(0, "JBD: recovery, exit status %d, "
11860                   "recovered transactions %u to %u\n",
11861                   err, info.start_transaction, info.end_transaction);
11862         jbd_debug(0, "JBD: Replayed %d and revoked %d/%d blocks\n",
11863                   info.nr_replays, info.nr_revoke_hits, info.nr_revokes);
11864
11865         /* Restart the log at the next transaction ID, thus invalidating
11866          * any existing commit records in the log. */
11867         journal->j_transaction_sequence = ++info.end_transaction;
11868
11869         journal_clear_revoke(journal);
11870         sync_blockdev(journal->j_fs_dev);
11871         return err;
11872 }
11873
11874 static int do_one_pass(journal_t *journal,
11875                         struct recovery_info *info, enum passtype pass)
11876 {
11877         unsigned int            first_commit_ID, next_commit_ID;
11878         unsigned long           next_log_block;
11879         int                     err, success = 0;
11880         journal_superblock_t *  sb;
11881         journal_header_t *      tmp;
11882         struct buffer_head *    bh;
11883         unsigned int            sequence;
11884         int                     blocktype;
11885
11886         /* Precompute the maximum metadata descriptors in a descriptor block */
11887         int                     MAX_BLOCKS_PER_DESC;
11888         MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
11889                                / sizeof(journal_block_tag_t));
11890
11891         /*
11892          * First thing is to establish what we expect to find in the log
11893          * (in terms of transaction IDs), and where (in terms of log
11894          * block offsets): query the superblock.
11895          */
11896
11897         sb = journal->j_superblock;
11898         next_commit_ID = ntohl(sb->s_sequence);
11899         next_log_block = ntohl(sb->s_start);
11900
11901         first_commit_ID = next_commit_ID;
11902         if (pass == PASS_SCAN)
11903                 info->start_transaction = first_commit_ID;
11904
11905         jbd_debug(1, "Starting recovery pass %d\n", pass);
11906
11907         /*
11908          * Now we walk through the log, transaction by transaction,
11909          * making sure that each transaction has a commit block in the
11910          * expected place.  Each complete transaction gets replayed back
11911          * into the main filesystem.
11912          */
11913
11914         while (1) {
11915                 int                     flags;
11916                 char *                  tagp;
11917                 journal_block_tag_t *   tag;
11918                 struct buffer_head *    obh;
11919                 struct buffer_head *    nbh;
11920
11921                 /* If we already know where to stop the log traversal,
11922                  * check right now that we haven't gone past the end of
11923                  * the log. */
11924
11925                 if (pass != PASS_SCAN)
11926                         if (tid_geq(next_commit_ID, info->end_transaction))
11927                                 break;
11928
11929                 jbd_debug(2, "Scanning for sequence ID %u at %lu/%lu\n",
11930                           next_commit_ID, next_log_block, journal->j_last);
11931
11932                 /* Skip over each chunk of the transaction looking
11933                  * either the next descriptor block or the final commit
11934                  * record. */
11935
11936                 jbd_debug(3, "JBD: checking block %ld\n", next_log_block);
11937                 err = jread(&bh, journal, next_log_block);
11938                 if (err)
11939                         goto failed;
11940
11941                 next_log_block++;
11942                 wrap(journal, next_log_block);
11943
11944                 /* What kind of buffer is it?
11945                  *
11946                  * If it is a descriptor block, check that it has the
11947                  * expected sequence number.  Otherwise, we're all done
11948                  * here. */
11949
11950                 tmp = (journal_header_t *)bh->b_data;
11951
11952                 if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
11953                         brelse(bh);
11954                         break;
11955                 }
11956
11957                 blocktype = ntohl(tmp->h_blocktype);
11958                 sequence = ntohl(tmp->h_sequence);
11959                 jbd_debug(3, "Found magic %d, sequence %d\n",
11960                           blocktype, sequence);
11961
11962                 if (sequence != next_commit_ID) {
11963                         brelse(bh);
11964                         break;
11965                 }
11966
11967                 /* OK, we have a valid descriptor block which matches
11968                  * all of the sequence number checks.  What are we going
11969                  * to do with it?  That depends on the pass... */
11970
11971                 switch(blocktype) {
11972                 case JFS_DESCRIPTOR_BLOCK:
11973                         /* If it is a valid descriptor block, replay it
11974                          * in pass REPLAY; otherwise, just skip over the
11975                          * blocks it describes. */
11976                         if (pass != PASS_REPLAY) {
11977                                 next_log_block +=
11978                                         count_tags(bh, journal->j_blocksize);
11979                                 wrap(journal, next_log_block);
11980                                 brelse(bh);
11981                                 continue;
11982                         }
11983
11984                         /* A descriptor block: we can now write all of
11985                          * the data blocks.  Yay, useful work is finally
11986                          * getting done here! */
11987
11988                         tagp = &bh->b_data[sizeof(journal_header_t)];
11989                         while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
11990                                <= journal->j_blocksize) {
11991                                 unsigned long io_block;
11992
11993                                 tag = (journal_block_tag_t *) tagp;
11994                                 flags = ntohl(tag->t_flags);
11995
11996                                 io_block = next_log_block++;
11997                                 wrap(journal, next_log_block);
11998                                 err = jread(&obh, journal, io_block);
11999                                 if (err) {
12000                                         /* Recover what we can, but
12001                                          * report failure at the end. */
12002                                         success = err;
12003                                         printk (KERN_ERR
12004                                                 "JBD: IO error %d recovering "
12005                                                 "block %ld in log\n",
12006                                                 err, io_block);
12007                                 } else {
12008                                         unsigned long blocknr;
12009
12010                                         J_ASSERT(obh != NULL);
12011                                         blocknr = ntohl(tag->t_blocknr);
12012
12013                                         /* If the block has been
12014                                          * revoked, then we're all done
12015                                          * here. */
12016                                         if (journal_test_revoke
12017                                             (journal, blocknr,
12018                                              next_commit_ID)) {
12019                                                 brelse(obh);
12020                                                 ++info->nr_revoke_hits;
12021                                                 goto skip_write;
12022                                         }
12023
12024                                         /* Find a buffer for the new
12025                                          * data being restored */
12026                                         nbh = getblk(journal->j_fs_dev,
12027                                                        blocknr,
12028                                                      journal->j_blocksize);
12029                                         if (nbh == NULL) {
12030                                                 printk(KERN_ERR
12031                                                        "JBD: Out of memory "
12032                                                        "during recovery.\n");
12033                                                 err = -ENOMEM;
12034                                                 brelse(bh);
12035                                                 brelse(obh);
12036                                                 goto failed;
12037                                         }
12038
12039                                         lock_buffer(nbh);
12040                                         memcpy(nbh->b_data, obh->b_data,
12041                                                         journal->j_blocksize);
12042                                         if (flags & JFS_FLAG_ESCAPE) {
12043                                                 *((unsigned int *)bh->b_data) =
12044                                                         htonl(JFS_MAGIC_NUMBER);
12045                                         }
12046
12047                                         BUFFER_TRACE(nbh, "marking dirty");
12048                                         mark_buffer_uptodate(nbh, 1);
12049                                         mark_buffer_dirty(nbh);
12050                                         BUFFER_TRACE(nbh, "marking uptodate");
12051                                         ++info->nr_replays;
12052                                         /* ll_rw_block(WRITE, 1, &nbh); */
12053                                         unlock_buffer(nbh);
12054                                         brelse(obh);
12055                                         brelse(nbh);
12056                                 }
12057
12058                         skip_write:
12059                                 tagp += sizeof(journal_block_tag_t);
12060                                 if (!(flags & JFS_FLAG_SAME_UUID))
12061                                         tagp += 16;
12062
12063                                 if (flags & JFS_FLAG_LAST_TAG)
12064                                         break;
12065                         }
12066
12067                         brelse(bh);
12068                         continue;
12069
12070                 case JFS_COMMIT_BLOCK:
12071                         /* Found an expected commit block: not much to
12072                          * do other than move on to the next sequence
12073                          * number. */
12074                         brelse(bh);
12075                         next_commit_ID++;
12076                         continue;
12077
12078                 case JFS_REVOKE_BLOCK:
12079                         /* If we aren't in the REVOKE pass, then we can
12080                          * just skip over this block. */
12081                         if (pass != PASS_REVOKE) {
12082                                 brelse(bh);
12083                                 continue;
12084                         }
12085
12086                         err = scan_revoke_records(journal, bh,
12087                                                   next_commit_ID, info);
12088                         brelse(bh);
12089                         if (err)
12090                                 goto failed;
12091                         continue;
12092
12093                 default:
12094                         jbd_debug(3, "Unrecognised magic %d, end of scan.\n",
12095                                   blocktype);
12096                         goto done;
12097                 }
12098         }
12099
12100  done:
12101         /*
12102          * We broke out of the log scan loop: either we came to the
12103          * known end of the log or we found an unexpected block in the
12104          * log.  If the latter happened, then we know that the "current"
12105          * transaction marks the end of the valid log.
12106          */
12107
12108         if (pass == PASS_SCAN)
12109                 info->end_transaction = next_commit_ID;
12110         else {
12111                 /* It's really bad news if different passes end up at
12112                  * different places (but possible due to IO errors). */
12113                 if (info->end_transaction != next_commit_ID) {
12114                         printk (KERN_ERR "JBD: recovery pass %d ended at "
12115                                 "transaction %u, expected %u\n",
12116                                 pass, next_commit_ID, info->end_transaction);
12117                         if (!success)
12118                                 success = -EIO;
12119                 }
12120         }
12121
12122         return success;
12123
12124  failed:
12125         return err;
12126 }
12127
12128
12129 /* Scan a revoke record, marking all blocks mentioned as revoked. */
12130
12131 static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
12132                                tid_t sequence, struct recovery_info *info)
12133 {
12134         journal_revoke_header_t *header;
12135         int offset, max;
12136
12137         header = (journal_revoke_header_t *) bh->b_data;
12138         offset = sizeof(journal_revoke_header_t);
12139         max = ntohl(header->r_count);
12140
12141         while (offset < max) {
12142                 unsigned long blocknr;
12143                 int err;
12144
12145                 blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
12146                 offset += 4;
12147                 err = journal_set_revoke(journal, blocknr, sequence);
12148                 if (err)
12149                         return err;
12150                 ++info->nr_revokes;
12151         }
12152         return 0;
12153 }
12154
12155
12156 /*
12157  * rehash.c --- rebuild hash tree directories
12158  *
12159  * This algorithm is designed for simplicity of implementation and to
12160  * pack the directory as much as possible.  It however requires twice
12161  * as much memory as the size of the directory.  The maximum size
12162  * directory supported using a 4k blocksize is roughly a gigabyte, and
12163  * so there may very well be problems with machines that don't have
12164  * virtual memory, and obscenely large directories.
12165  *
12166  * An alternate algorithm which is much more disk intensive could be
12167  * written, and probably will need to be written in the future.  The
12168  * design goals of such an algorithm are: (a) use (roughly) constant
12169  * amounts of memory, no matter how large the directory, (b) the
12170  * directory must be safe at all times, even if e2fsck is interrupted
12171  * in the middle, (c) we must use minimal amounts of extra disk
12172  * blocks.  This pretty much requires an incremental approach, where
12173  * we are reading from one part of the directory, and inserting into
12174  * the front half.  So the algorithm will have to keep track of a
12175  * moving block boundary between the new tree and the old tree, and
12176  * files will need to be moved from the old directory and inserted
12177  * into the new tree.  If the new directory requires space which isn't
12178  * yet available, blocks from the beginning part of the old directory
12179  * may need to be moved to the end of the directory to make room for
12180  * the new tree:
12181  *
12182  *    --------------------------------------------------------
12183  *    |  new tree   |        | old tree                      |
12184  *    --------------------------------------------------------
12185  *                  ^ ptr    ^ptr
12186  *                tail new   head old
12187  *
12188  * This is going to be a pain in the tuckus to implement, and will
12189  * require a lot more disk accesses.  So I'm going to skip it for now;
12190  * it's only really going to be an issue for really, really big
12191  * filesystems (when we reach the level of tens of millions of files
12192  * in a single directory).  It will probably be easier to simply
12193  * require that e2fsck use VM first.
12194  */
12195
12196 struct fill_dir_struct {
12197         char *buf;
12198         struct ext2_inode *inode;
12199         int err;
12200         e2fsck_t ctx;
12201         struct hash_entry *harray;
12202         int max_array, num_array;
12203         int dir_size;
12204         int compress;
12205         ino_t parent;
12206 };
12207
12208 struct hash_entry {
12209         ext2_dirhash_t  hash;
12210         ext2_dirhash_t  minor_hash;
12211         struct ext2_dir_entry   *dir;
12212 };
12213
12214 struct out_dir {
12215         int             num;
12216         int             max;
12217         char            *buf;
12218         ext2_dirhash_t  *hashes;
12219 };
12220
12221 static int fill_dir_block(ext2_filsys fs,
12222                           blk_t *block_nr,
12223                           e2_blkcnt_t blockcnt,
12224                           blk_t ref_block FSCK_ATTR((unused)),
12225                           int ref_offset FSCK_ATTR((unused)),
12226                           void *priv_data)
12227 {
12228         struct fill_dir_struct  *fd = (struct fill_dir_struct *) priv_data;
12229         struct hash_entry       *new_array, *ent;
12230         struct ext2_dir_entry   *dirent;
12231         char                    *dir;
12232         unsigned int            offset, dir_offset;
12233
12234         if (blockcnt < 0)
12235                 return 0;
12236
12237         offset = blockcnt * fs->blocksize;
12238         if (offset + fs->blocksize > fd->inode->i_size) {
12239                 fd->err = EXT2_ET_DIR_CORRUPTED;
12240                 return BLOCK_ABORT;
12241         }
12242         dir = (fd->buf+offset);
12243         if (HOLE_BLKADDR(*block_nr)) {
12244                 memset(dir, 0, fs->blocksize);
12245                 dirent = (struct ext2_dir_entry *) dir;
12246                 dirent->rec_len = fs->blocksize;
12247         } else {
12248                 fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
12249                 if (fd->err)
12250                         return BLOCK_ABORT;
12251         }
12252         /* While the directory block is "hot", index it. */
12253         dir_offset = 0;
12254         while (dir_offset < fs->blocksize) {
12255                 dirent = (struct ext2_dir_entry *) (dir + dir_offset);
12256                 if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
12257                     (dirent->rec_len < 8) ||
12258                     ((dirent->rec_len % 4) != 0) ||
12259                     (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
12260                         fd->err = EXT2_ET_DIR_CORRUPTED;
12261                         return BLOCK_ABORT;
12262                 }
12263                 dir_offset += dirent->rec_len;
12264                 if (dirent->inode == 0)
12265                         continue;
12266                 if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
12267                     (dirent->name[0] == '.'))
12268                         continue;
12269                 if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
12270                     (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
12271                         fd->parent = dirent->inode;
12272                         continue;
12273                 }
12274                 if (fd->num_array >= fd->max_array) {
12275                         new_array = realloc(fd->harray,
12276                             sizeof(struct hash_entry) * (fd->max_array+500));
12277                         if (!new_array) {
12278                                 fd->err = ENOMEM;
12279                                 return BLOCK_ABORT;
12280                         }
12281                         fd->harray = new_array;
12282                         fd->max_array += 500;
12283                 }
12284                 ent = fd->harray + fd->num_array++;
12285                 ent->dir = dirent;
12286                 fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
12287                 if (fd->compress)
12288                         ent->hash = ent->minor_hash = 0;
12289                 else {
12290                         fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
12291                                                  dirent->name,
12292                                                  dirent->name_len & 0xFF,
12293                                                  fs->super->s_hash_seed,
12294                                                  &ent->hash, &ent->minor_hash);
12295                         if (fd->err)
12296                                 return BLOCK_ABORT;
12297                 }
12298         }
12299
12300         return 0;
12301 }
12302
12303 /* Used for sorting the hash entry */
12304 static EXT2_QSORT_TYPE name_cmp(const void *a, const void *b)
12305 {
12306         const struct hash_entry *he_a = (const struct hash_entry *) a;
12307         const struct hash_entry *he_b = (const struct hash_entry *) b;
12308         int     ret;
12309         int     min_len;
12310
12311         min_len = he_a->dir->name_len;
12312         if (min_len > he_b->dir->name_len)
12313                 min_len = he_b->dir->name_len;
12314
12315         ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
12316         if (ret == 0) {
12317                 if (he_a->dir->name_len > he_b->dir->name_len)
12318                         ret = 1;
12319                 else if (he_a->dir->name_len < he_b->dir->name_len)
12320                         ret = -1;
12321                 else
12322                         ret = he_b->dir->inode - he_a->dir->inode;
12323         }
12324         return ret;
12325 }
12326
12327 /* Used for sorting the hash entry */
12328 static EXT2_QSORT_TYPE hash_cmp(const void *a, const void *b)
12329 {
12330         const struct hash_entry *he_a = (const struct hash_entry *) a;
12331         const struct hash_entry *he_b = (const struct hash_entry *) b;
12332         int     ret;
12333
12334         if (he_a->hash > he_b->hash)
12335                 ret = 1;
12336         else if (he_a->hash < he_b->hash)
12337                 ret = -1;
12338         else {
12339                 if (he_a->minor_hash > he_b->minor_hash)
12340                         ret = 1;
12341                 else if (he_a->minor_hash < he_b->minor_hash)
12342                         ret = -1;
12343                 else
12344                         ret = name_cmp(a, b);
12345         }
12346         return ret;
12347 }
12348
12349 static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
12350                                 int blocks)
12351 {
12352         void                    *new_mem;
12353
12354         if (outdir->max) {
12355                 new_mem = realloc(outdir->buf, blocks * fs->blocksize);
12356                 if (!new_mem)
12357                         return ENOMEM;
12358                 outdir->buf = new_mem;
12359                 new_mem = realloc(outdir->hashes,
12360                                   blocks * sizeof(ext2_dirhash_t));
12361                 if (!new_mem)
12362                         return ENOMEM;
12363                 outdir->hashes = new_mem;
12364         } else {
12365                 outdir->buf = malloc(blocks * fs->blocksize);
12366                 outdir->hashes = malloc(blocks * sizeof(ext2_dirhash_t));
12367                 outdir->num = 0;
12368         }
12369         outdir->max = blocks;
12370         return 0;
12371 }
12372
12373 static void free_out_dir(struct out_dir *outdir)
12374 {
12375         if (outdir->buf)
12376                 free(outdir->buf);
12377         if (outdir->hashes)
12378                 free(outdir->hashes);
12379         outdir->max = 0;
12380         outdir->num =0;
12381 }
12382
12383 static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
12384                          char ** ret)
12385 {
12386         errcode_t       retval;
12387
12388         if (outdir->num >= outdir->max) {
12389                 retval = alloc_size_dir(fs, outdir, outdir->max + 50);
12390                 if (retval)
12391                         return retval;
12392         }
12393         *ret = outdir->buf + (outdir->num++ * fs->blocksize);
12394         memset(*ret, 0, fs->blocksize);
12395         return 0;
12396 }
12397
12398 /*
12399  * This function is used to make a unique filename.  We do this by
12400  * appending ~0, and then incrementing the number.  However, we cannot
12401  * expand the length of the filename beyond the padding available in
12402  * the directory entry.
12403  */
12404 static void mutate_name(char *str, __u16 *len)
12405 {
12406         int     i;
12407         __u16   l = *len & 0xFF, h = *len & 0xff00;
12408
12409         /*
12410          * First check to see if it looks the name has been mutated
12411          * already
12412          */
12413         for (i = l-1; i > 0; i--) {
12414                 if (!isdigit(str[i]))
12415                         break;
12416         }
12417         if ((i == l-1) || (str[i] != '~')) {
12418                 if (((l-1) & 3) < 2)
12419                         l += 2;
12420                 else
12421                         l = (l+3) & ~3;
12422                 str[l-2] = '~';
12423                 str[l-1] = '0';
12424                 *len = l | h;
12425                 return;
12426         }
12427         for (i = l-1; i >= 0; i--) {
12428                 if (isdigit(str[i])) {
12429                         if (str[i] == '9')
12430                                 str[i] = '0';
12431                         else {
12432                                 str[i]++;
12433                                 return;
12434                         }
12435                         continue;
12436                 }
12437                 if (i == 1) {
12438                         if (str[0] == 'z')
12439                                 str[0] = 'A';
12440                         else if (str[0] == 'Z') {
12441                                 str[0] = '~';
12442                                 str[1] = '0';
12443                         } else
12444                                 str[0]++;
12445                 } else if (i > 0) {
12446                         str[i] = '1';
12447                         str[i-1] = '~';
12448                 } else {
12449                         if (str[0] == '~')
12450                                 str[0] = 'a';
12451                         else
12452                                 str[0]++;
12453                 }
12454                 break;
12455         }
12456 }
12457
12458 static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
12459                                     ext2_ino_t ino,
12460                                     struct fill_dir_struct *fd)
12461 {
12462         struct problem_context  pctx;
12463         struct hash_entry       *ent, *prev;
12464         int                     i, j;
12465         int                     fixed = 0;
12466         char                    new_name[256];
12467         __u16                   new_len;
12468
12469         clear_problem_context(&pctx);
12470         pctx.ino = ino;
12471
12472         for (i=1; i < fd->num_array; i++) {
12473                 ent = fd->harray + i;
12474                 prev = ent - 1;
12475                 if (!ent->dir->inode ||
12476                     ((ent->dir->name_len & 0xFF) !=
12477                      (prev->dir->name_len & 0xFF)) ||
12478                     (strncmp(ent->dir->name, prev->dir->name,
12479                              ent->dir->name_len & 0xFF)))
12480                         continue;
12481                 pctx.dirent = ent->dir;
12482                 if ((ent->dir->inode == prev->dir->inode) &&
12483                     fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
12484                         e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
12485                         ent->dir->inode = 0;
12486                         fixed++;
12487                         continue;
12488                 }
12489                 memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
12490                 new_len = ent->dir->name_len;
12491                 mutate_name(new_name, &new_len);
12492                 for (j=0; j < fd->num_array; j++) {
12493                         if ((i==j) ||
12494                             ((ent->dir->name_len & 0xFF) !=
12495                              (fd->harray[j].dir->name_len & 0xFF)) ||
12496                             (strncmp(new_name, fd->harray[j].dir->name,
12497                                      new_len & 0xFF)))
12498                                 continue;
12499                         mutate_name(new_name, &new_len);
12500
12501                         j = -1;
12502                 }
12503                 new_name[new_len & 0xFF] = 0;
12504                 pctx.str = new_name;
12505                 if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
12506                         memcpy(ent->dir->name, new_name, new_len & 0xFF);
12507                         ent->dir->name_len = new_len;
12508                         ext2fs_dirhash(fs->super->s_def_hash_version,
12509                                        ent->dir->name,
12510                                        ent->dir->name_len & 0xFF,
12511                                        fs->super->s_hash_seed,
12512                                        &ent->hash, &ent->minor_hash);
12513                         fixed++;
12514                 }
12515         }
12516         return fixed;
12517 }
12518
12519
12520 static errcode_t copy_dir_entries(ext2_filsys fs,
12521                                   struct fill_dir_struct *fd,
12522                                   struct out_dir *outdir)
12523 {
12524         errcode_t               retval;
12525         char                    *block_start;
12526         struct hash_entry       *ent;
12527         struct ext2_dir_entry   *dirent;
12528         int                     i, rec_len, left;
12529         ext2_dirhash_t          prev_hash;
12530         int                     offset;
12531
12532         outdir->max = 0;
12533         retval = alloc_size_dir(fs, outdir,
12534                                 (fd->dir_size / fs->blocksize) + 2);
12535         if (retval)
12536                 return retval;
12537         outdir->num = fd->compress ? 0 : 1;
12538         offset = 0;
12539         outdir->hashes[0] = 0;
12540         prev_hash = 1;
12541         if ((retval = get_next_block(fs, outdir, &block_start)))
12542                 return retval;
12543         dirent = (struct ext2_dir_entry *) block_start;
12544         left = fs->blocksize;
12545         for (i=0; i < fd->num_array; i++) {
12546                 ent = fd->harray + i;
12547                 if (ent->dir->inode == 0)
12548                         continue;
12549                 rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
12550                 if (rec_len > left) {
12551                         if (left)
12552                                 dirent->rec_len += left;
12553                         if ((retval = get_next_block(fs, outdir,
12554                                                       &block_start)))
12555                                 return retval;
12556                         offset = 0;
12557                 }
12558                 left = fs->blocksize - offset;
12559                 dirent = (struct ext2_dir_entry *) (block_start + offset);
12560                 if (offset == 0) {
12561                         if (ent->hash == prev_hash)
12562                                 outdir->hashes[outdir->num-1] = ent->hash | 1;
12563                         else
12564                                 outdir->hashes[outdir->num-1] = ent->hash;
12565                 }
12566                 dirent->inode = ent->dir->inode;
12567                 dirent->name_len = ent->dir->name_len;
12568                 dirent->rec_len = rec_len;
12569                 memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
12570                 offset += rec_len;
12571                 left -= rec_len;
12572                 if (left < 12) {
12573                         dirent->rec_len += left;
12574                         offset += left;
12575                         left = 0;
12576                 }
12577                 prev_hash = ent->hash;
12578         }
12579         if (left)
12580                 dirent->rec_len += left;
12581
12582         return 0;
12583 }
12584
12585
12586 static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
12587                                     ext2_ino_t ino, ext2_ino_t parent)
12588 {
12589         struct ext2_dir_entry           *dir;
12590         struct ext2_dx_root_info        *root;
12591         struct ext2_dx_countlimit       *limits;
12592         int                             filetype = 0;
12593
12594         if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
12595                 filetype = EXT2_FT_DIR << 8;
12596
12597         memset(buf, 0, fs->blocksize);
12598         dir = (struct ext2_dir_entry *) buf;
12599         dir->inode = ino;
12600         dir->name[0] = '.';
12601         dir->name_len = 1 | filetype;
12602         dir->rec_len = 12;
12603         dir = (struct ext2_dir_entry *) (buf + 12);
12604         dir->inode = parent;
12605         dir->name[0] = '.';
12606         dir->name[1] = '.';
12607         dir->name_len = 2 | filetype;
12608         dir->rec_len = fs->blocksize - 12;
12609
12610         root = (struct ext2_dx_root_info *) (buf+24);
12611         root->reserved_zero = 0;
12612         root->hash_version = fs->super->s_def_hash_version;
12613         root->info_length = 8;
12614         root->indirect_levels = 0;
12615         root->unused_flags = 0;
12616
12617         limits = (struct ext2_dx_countlimit *) (buf+32);
12618         limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
12619         limits->count = 0;
12620
12621         return root;
12622 }
12623
12624
12625 static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
12626 {
12627         struct ext2_dir_entry           *dir;
12628         struct ext2_dx_countlimit       *limits;
12629
12630         memset(buf, 0, fs->blocksize);
12631         dir = (struct ext2_dir_entry *) buf;
12632         dir->inode = 0;
12633         dir->rec_len = fs->blocksize;
12634
12635         limits = (struct ext2_dx_countlimit *) (buf+8);
12636         limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
12637         limits->count = 0;
12638
12639         return (struct ext2_dx_entry *) limits;
12640 }
12641
12642 /*
12643  * This function takes the leaf nodes which have been written in
12644  * outdir, and populates the root node and any necessary interior nodes.
12645  */
12646 static errcode_t calculate_tree(ext2_filsys fs,
12647                                 struct out_dir *outdir,
12648                                 ext2_ino_t ino,
12649                                 ext2_ino_t parent)
12650 {
12651         struct ext2_dx_root_info        *root_info;
12652         struct ext2_dx_entry            *root, *dx_ent = 0;
12653         struct ext2_dx_countlimit       *root_limit, *limit;
12654         errcode_t                       retval;
12655         char                            * block_start;
12656         int                             i, c1, c2, nblks;
12657         int                             limit_offset, root_offset;
12658
12659         root_info = set_root_node(fs, outdir->buf, ino, parent);
12660         root_offset = limit_offset = ((char *) root_info - outdir->buf) +
12661                 root_info->info_length;
12662         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
12663         c1 = root_limit->limit;
12664         nblks = outdir->num;
12665
12666         /* Write out the pointer blocks */
12667         if (nblks-1 <= c1) {
12668                 /* Just write out the root block, and we're done */
12669                 root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
12670                 for (i=1; i < nblks; i++) {
12671                         root->block = ext2fs_cpu_to_le32(i);
12672                         if (i != 1)
12673                                 root->hash =
12674                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
12675                         root++;
12676                         c1--;
12677                 }
12678         } else {
12679                 c2 = 0;
12680                 limit = 0;
12681                 root_info->indirect_levels = 1;
12682                 for (i=1; i < nblks; i++) {
12683                         if (c1 == 0)
12684                                 return ENOSPC;
12685                         if (c2 == 0) {
12686                                 if (limit)
12687                                         limit->limit = limit->count =
12688                 ext2fs_cpu_to_le16(limit->limit);
12689                                 root = (struct ext2_dx_entry *)
12690                                         (outdir->buf + root_offset);
12691                                 root->block = ext2fs_cpu_to_le32(outdir->num);
12692                                 if (i != 1)
12693                                         root->hash =
12694                         ext2fs_cpu_to_le32(outdir->hashes[i]);
12695                                 if ((retval =  get_next_block(fs, outdir,
12696                                                               &block_start)))
12697                                         return retval;
12698                                 dx_ent = set_int_node(fs, block_start);
12699                                 limit = (struct ext2_dx_countlimit *) dx_ent;
12700                                 c2 = limit->limit;
12701                                 root_offset += sizeof(struct ext2_dx_entry);
12702                                 c1--;
12703                         }
12704                         dx_ent->block = ext2fs_cpu_to_le32(i);
12705                         if (c2 != limit->limit)
12706                                 dx_ent->hash =
12707                                         ext2fs_cpu_to_le32(outdir->hashes[i]);
12708                         dx_ent++;
12709                         c2--;
12710                 }
12711                 limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
12712                 limit->limit = ext2fs_cpu_to_le16(limit->limit);
12713         }
12714         root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
12715         root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
12716         root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
12717
12718         return 0;
12719 }
12720
12721 struct write_dir_struct {
12722         struct out_dir *outdir;
12723         errcode_t       err;
12724         e2fsck_t        ctx;
12725         int             cleared;
12726 };
12727
12728 /*
12729  * Helper function which writes out a directory block.
12730  */
12731 static int write_dir_block(ext2_filsys fs,
12732                            blk_t        *block_nr,
12733                            e2_blkcnt_t blockcnt,
12734                            blk_t ref_block FSCK_ATTR((unused)),
12735                            int ref_offset FSCK_ATTR((unused)),
12736                            void *priv_data)
12737 {
12738         struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
12739         blk_t   blk;
12740         char    *dir;
12741
12742         if (*block_nr == 0)
12743                 return 0;
12744         if (blockcnt >= wd->outdir->num) {
12745                 e2fsck_read_bitmaps(wd->ctx);
12746                 blk = *block_nr;
12747                 ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
12748                 ext2fs_block_alloc_stats(fs, blk, -1);
12749                 *block_nr = 0;
12750                 wd->cleared++;
12751                 return BLOCK_CHANGED;
12752         }
12753         if (blockcnt < 0)
12754                 return 0;
12755
12756         dir = wd->outdir->buf + (blockcnt * fs->blocksize);
12757         wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
12758         if (wd->err)
12759                 return BLOCK_ABORT;
12760         return 0;
12761 }
12762
12763 static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
12764                                  struct out_dir *outdir,
12765                                  ext2_ino_t ino, int compress)
12766 {
12767         struct write_dir_struct wd;
12768         errcode_t       retval;
12769         struct ext2_inode       inode;
12770
12771         retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
12772         if (retval)
12773                 return retval;
12774
12775         wd.outdir = outdir;
12776         wd.err = 0;
12777         wd.ctx = ctx;
12778         wd.cleared = 0;
12779
12780         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
12781                                        write_dir_block, &wd);
12782         if (retval)
12783                 return retval;
12784         if (wd.err)
12785                 return wd.err;
12786
12787         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
12788         if (compress)
12789                 inode.i_flags &= ~EXT2_INDEX_FL;
12790         else
12791                 inode.i_flags |= EXT2_INDEX_FL;
12792         inode.i_size = outdir->num * fs->blocksize;
12793         inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
12794         e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
12795
12796         return 0;
12797 }
12798
12799 static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
12800 {
12801         ext2_filsys             fs = ctx->fs;
12802         errcode_t               retval;
12803         struct ext2_inode       inode;
12804         char                    *dir_buf = 0;
12805         struct fill_dir_struct  fd;
12806         struct out_dir          outdir;
12807
12808         outdir.max = outdir.num = 0;
12809         outdir.buf = 0;
12810         outdir.hashes = 0;
12811         e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
12812
12813         retval = ENOMEM;
12814         fd.harray = 0;
12815         dir_buf = malloc(inode.i_size);
12816         if (!dir_buf)
12817                 goto errout;
12818
12819         fd.max_array = inode.i_size / 32;
12820         fd.num_array = 0;
12821         fd.harray = malloc(fd.max_array * sizeof(struct hash_entry));
12822         if (!fd.harray)
12823                 goto errout;
12824
12825         fd.ctx = ctx;
12826         fd.buf = dir_buf;
12827         fd.inode = &inode;
12828         fd.err = 0;
12829         fd.dir_size = 0;
12830         fd.compress = 0;
12831         if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
12832             (inode.i_size / fs->blocksize) < 2)
12833                 fd.compress = 1;
12834         fd.parent = 0;
12835
12836         /* Read in the entire directory into memory */
12837         retval = ext2fs_block_iterate2(fs, ino, 0, 0,
12838                                        fill_dir_block, &fd);
12839         if (fd.err) {
12840                 retval = fd.err;
12841                 goto errout;
12842         }
12843
12844 #if 0
12845         printf("%d entries (%d bytes) found in inode %d\n",
12846                fd.num_array, fd.dir_size, ino);
12847 #endif
12848
12849         /* Sort the list */
12850 resort:
12851         if (fd.compress)
12852                 qsort(fd.harray+2, fd.num_array-2,
12853                       sizeof(struct hash_entry), name_cmp);
12854         else
12855                 qsort(fd.harray, fd.num_array,
12856                       sizeof(struct hash_entry), hash_cmp);
12857
12858         /*
12859          * Look for duplicates
12860          */
12861         if (duplicate_search_and_fix(ctx, fs, ino, &fd))
12862                 goto resort;
12863
12864         if (ctx->options & E2F_OPT_NO) {
12865                 retval = 0;
12866                 goto errout;
12867         }
12868
12869         /*
12870          * Copy the directory entries.  In a htree directory these
12871          * will become the leaf nodes.
12872          */
12873         retval = copy_dir_entries(fs, &fd, &outdir);
12874         if (retval)
12875                 goto errout;
12876
12877         free(dir_buf); dir_buf = 0;
12878
12879         if (!fd.compress) {
12880                 /* Calculate the interior nodes */
12881                 retval = calculate_tree(fs, &outdir, ino, fd.parent);
12882                 if (retval)
12883                         goto errout;
12884         }
12885
12886         retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
12887         if (retval)
12888                 goto errout;
12889
12890 errout:
12891         if (dir_buf)
12892                 free(dir_buf);
12893         if (fd.harray)
12894                 free(fd.harray);
12895
12896         free_out_dir(&outdir);
12897         return retval;
12898 }
12899
12900 void e2fsck_rehash_directories(e2fsck_t ctx)
12901 {
12902         struct problem_context  pctx;
12903 #ifdef RESOURCE_TRACK
12904         struct resource_track   rtrack;
12905 #endif
12906         struct dir_info         *dir;
12907         ext2_u32_iterate        iter;
12908         ext2_ino_t              ino;
12909         errcode_t               retval;
12910         int                     i, cur, max, all_dirs, dir_index, first = 1;
12911
12912 #ifdef RESOURCE_TRACK
12913         init_resource_track(&rtrack);
12914 #endif
12915
12916         all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
12917
12918         if (!ctx->dirs_to_hash && !all_dirs)
12919                 return;
12920
12921         e2fsck_get_lost_and_found(ctx, 0);
12922
12923         clear_problem_context(&pctx);
12924
12925         dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
12926         cur = 0;
12927         if (all_dirs) {
12928                 i = 0;
12929                 max = e2fsck_get_num_dirinfo(ctx);
12930         } else {
12931                 retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
12932                                                        &iter);
12933                 if (retval) {
12934                         pctx.errcode = retval;
12935                         fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
12936                         return;
12937                 }
12938                 max = ext2fs_u32_list_count(ctx->dirs_to_hash);
12939         }
12940         while (1) {
12941                 if (all_dirs) {
12942                         if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
12943                                 break;
12944                         ino = dir->ino;
12945                 } else {
12946                         if (!ext2fs_u32_list_iterate(iter, &ino))
12947                                 break;
12948                 }
12949                 if (ino == ctx->lost_and_found)
12950                         continue;
12951                 pctx.dir = ino;
12952                 if (first) {
12953                         fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
12954                         first = 0;
12955                 }
12956 #if 0
12957                 fix_problem(ctx, PR_3A_OPTIMIZE_DIR, &pctx);
12958 #endif
12959                 pctx.errcode = e2fsck_rehash_dir(ctx, ino);
12960                 if (pctx.errcode) {
12961                         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
12962                         fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
12963                 }
12964                 if (ctx->progress && !ctx->progress_fd)
12965                         e2fsck_simple_progress(ctx, "Rebuilding directory",
12966                                100.0 * (float) (++cur) / (float) max, ino);
12967         }
12968         end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
12969         if (!all_dirs)
12970                 ext2fs_u32_list_iterate_end(iter);
12971
12972         if (ctx->dirs_to_hash)
12973                 ext2fs_u32_list_free(ctx->dirs_to_hash);
12974         ctx->dirs_to_hash = 0;
12975
12976 #ifdef RESOURCE_TRACK
12977         if (ctx->options & E2F_OPT_TIME2) {
12978                 e2fsck_clear_progbar(ctx);
12979                 print_resource_track("Pass 3A", &rtrack);
12980         }
12981 #endif
12982 }
12983
12984 /*
12985  * linux/fs/revoke.c
12986  *
12987  * Journal revoke routines for the generic filesystem journaling code;
12988  * part of the ext2fs journaling system.
12989  *
12990  * Revoke is the mechanism used to prevent old log records for deleted
12991  * metadata from being replayed on top of newer data using the same
12992  * blocks.  The revoke mechanism is used in two separate places:
12993  *
12994  * + Commit: during commit we write the entire list of the current
12995  *   transaction's revoked blocks to the journal
12996  *
12997  * + Recovery: during recovery we record the transaction ID of all
12998  *   revoked blocks.  If there are multiple revoke records in the log
12999  *   for a single block, only the last one counts, and if there is a log
13000  *   entry for a block beyond the last revoke, then that log entry still
13001  *   gets replayed.
13002  *
13003  * We can get interactions between revokes and new log data within a
13004  * single transaction:
13005  *
13006  * Block is revoked and then journaled:
13007  *   The desired end result is the journaling of the new block, so we
13008  *   cancel the revoke before the transaction commits.
13009  *
13010  * Block is journaled and then revoked:
13011  *   The revoke must take precedence over the write of the block, so we
13012  *   need either to cancel the journal entry or to write the revoke
13013  *   later in the log than the log block.  In this case, we choose the
13014  *   latter: journaling a block cancels any revoke record for that block
13015  *   in the current transaction, so any revoke for that block in the
13016  *   transaction must have happened after the block was journaled and so
13017  *   the revoke must take precedence.
13018  *
13019  * Block is revoked and then written as data:
13020  *   The data write is allowed to succeed, but the revoke is _not_
13021  *   cancelled.  We still need to prevent old log records from
13022  *   overwriting the new data.  We don't even need to clear the revoke
13023  *   bit here.
13024  *
13025  * Revoke information on buffers is a tri-state value:
13026  *
13027  * RevokeValid clear:   no cached revoke status, need to look it up
13028  * RevokeValid set, Revoked clear:
13029  *                      buffer has not been revoked, and cancel_revoke
13030  *                      need do nothing.
13031  * RevokeValid set, Revoked set:
13032  *                      buffer has been revoked.
13033  */
13034
13035 static kmem_cache_t *revoke_record_cache;
13036 static kmem_cache_t *revoke_table_cache;
13037
13038 /* Each revoke record represents one single revoked block.  During
13039    journal replay, this involves recording the transaction ID of the
13040    last transaction to revoke this block. */
13041
13042 struct jbd_revoke_record_s
13043 {
13044         struct list_head  hash;
13045         tid_t             sequence;     /* Used for recovery only */
13046         unsigned long     blocknr;
13047 };
13048
13049
13050 /* The revoke table is just a simple hash table of revoke records. */
13051 struct jbd_revoke_table_s
13052 {
13053         /* It is conceivable that we might want a larger hash table
13054          * for recovery.  Must be a power of two. */
13055         int               hash_size;
13056         int               hash_shift;
13057         struct list_head *hash_table;
13058 };
13059
13060
13061 /* Utility functions to maintain the revoke table */
13062
13063 /* Borrowed from buffer.c: this is a tried and tested block hash function */
13064 static inline int hash(journal_t *journal, unsigned long block)
13065 {
13066         struct jbd_revoke_table_s *table = journal->j_revoke;
13067         int hash_shift = table->hash_shift;
13068
13069         return ((block << (hash_shift - 6)) ^
13070                 (block >> 13) ^
13071                 (block << (hash_shift - 12))) & (table->hash_size - 1);
13072 }
13073
13074 static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
13075                               tid_t seq)
13076 {
13077         struct list_head *hash_list;
13078         struct jbd_revoke_record_s *record;
13079
13080         record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
13081         if (!record)
13082                 goto oom;
13083
13084         record->sequence = seq;
13085         record->blocknr = blocknr;
13086         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
13087         list_add(&record->hash, hash_list);
13088         return 0;
13089
13090 oom:
13091         return -ENOMEM;
13092 }
13093
13094 /* Find a revoke record in the journal's hash table. */
13095
13096 static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
13097                                                       unsigned long blocknr)
13098 {
13099         struct list_head *hash_list;
13100         struct jbd_revoke_record_s *record;
13101
13102         hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
13103
13104         record = (struct jbd_revoke_record_s *) hash_list->next;
13105         while (&(record->hash) != hash_list) {
13106                 if (record->blocknr == blocknr)
13107                         return record;
13108                 record = (struct jbd_revoke_record_s *) record->hash.next;
13109         }
13110         return NULL;
13111 }
13112
13113 int journal_init_revoke_caches(void)
13114 {
13115         revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
13116         if (revoke_record_cache == 0)
13117                 return -ENOMEM;
13118
13119         revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
13120         if (revoke_table_cache == 0) {
13121                 do_cache_destroy(revoke_record_cache);
13122                 revoke_record_cache = NULL;
13123                 return -ENOMEM;
13124         }
13125         return 0;
13126 }
13127
13128 void journal_destroy_revoke_caches(void)
13129 {
13130         do_cache_destroy(revoke_record_cache);
13131         revoke_record_cache = 0;
13132         do_cache_destroy(revoke_table_cache);
13133         revoke_table_cache = 0;
13134 }
13135
13136 /* Initialise the revoke table for a given journal to a given size. */
13137
13138 int journal_init_revoke(journal_t *journal, int hash_size)
13139 {
13140         int shift, tmp;
13141
13142         J_ASSERT (journal->j_revoke == NULL);
13143
13144         journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
13145         if (!journal->j_revoke)
13146                 return -ENOMEM;
13147
13148         /* Check that the hash_size is a power of two */
13149         J_ASSERT ((hash_size & (hash_size-1)) == 0);
13150
13151         journal->j_revoke->hash_size = hash_size;
13152
13153         shift = 0;
13154         tmp = hash_size;
13155         while((tmp >>= 1UL) != 0UL)
13156                 shift++;
13157         journal->j_revoke->hash_shift = shift;
13158
13159         journal->j_revoke->hash_table = malloc(hash_size * sizeof(struct list_head));
13160         if (!journal->j_revoke->hash_table) {
13161                 free(journal->j_revoke);
13162                 journal->j_revoke = NULL;
13163                 return -ENOMEM;
13164         }
13165
13166         for (tmp = 0; tmp < hash_size; tmp++)
13167                 INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
13168
13169         return 0;
13170 }
13171
13172 /* Destoy a journal's revoke table.  The table must already be empty! */
13173
13174 void journal_destroy_revoke(journal_t *journal)
13175 {
13176         struct jbd_revoke_table_s *table;
13177         struct list_head *hash_list;
13178         int i;
13179
13180         table = journal->j_revoke;
13181         if (!table)
13182                 return;
13183
13184         for (i=0; i<table->hash_size; i++) {
13185                 hash_list = &table->hash_table[i];
13186                 J_ASSERT (list_empty(hash_list));
13187         }
13188
13189         free(table->hash_table);
13190         free(table);
13191         journal->j_revoke = NULL;
13192 }
13193
13194 /*
13195  * Revoke support for recovery.
13196  *
13197  * Recovery needs to be able to:
13198  *
13199  *  record all revoke records, including the tid of the latest instance
13200  *  of each revoke in the journal
13201  *
13202  *  check whether a given block in a given transaction should be replayed
13203  *  (ie. has not been revoked by a revoke record in that or a subsequent
13204  *  transaction)
13205  *
13206  *  empty the revoke table after recovery.
13207  */
13208
13209 /*
13210  * First, setting revoke records.  We create a new revoke record for
13211  * every block ever revoked in the log as we scan it for recovery, and
13212  * we update the existing records if we find multiple revokes for a
13213  * single block.
13214  */
13215
13216 int journal_set_revoke(journal_t *journal, unsigned long blocknr,
13217                        tid_t sequence)
13218 {
13219         struct jbd_revoke_record_s *record;
13220
13221         record = find_revoke_record(journal, blocknr);
13222         if (record) {
13223                 /* If we have multiple occurences, only record the
13224                  * latest sequence number in the hashed record */
13225                 if (tid_gt(sequence, record->sequence))
13226                         record->sequence = sequence;
13227                 return 0;
13228         }
13229         return insert_revoke_hash(journal, blocknr, sequence);
13230 }
13231
13232 /*
13233  * Test revoke records.  For a given block referenced in the log, has
13234  * that block been revoked?  A revoke record with a given transaction
13235  * sequence number revokes all blocks in that transaction and earlier
13236  * ones, but later transactions still need replayed.
13237  */
13238
13239 int journal_test_revoke(journal_t *journal, unsigned long blocknr,
13240                         tid_t sequence)
13241 {
13242         struct jbd_revoke_record_s *record;
13243
13244         record = find_revoke_record(journal, blocknr);
13245         if (!record)
13246                 return 0;
13247         if (tid_gt(sequence, record->sequence))
13248                 return 0;
13249         return 1;
13250 }
13251
13252 /*
13253  * Finally, once recovery is over, we need to clear the revoke table so
13254  * that it can be reused by the running filesystem.
13255  */
13256
13257 void journal_clear_revoke(journal_t *journal)
13258 {
13259         int i;
13260         struct list_head *hash_list;
13261         struct jbd_revoke_record_s *record;
13262         struct jbd_revoke_table_s *revoke_var;
13263
13264         revoke_var = journal->j_revoke;
13265
13266         for (i = 0; i < revoke_var->hash_size; i++) {
13267                 hash_list = &revoke_var->hash_table[i];
13268                 while (!list_empty(hash_list)) {
13269                         record = (struct jbd_revoke_record_s*) hash_list->next;
13270                         list_del(&record->hash);
13271                         free(record);
13272                 }
13273         }
13274 }
13275
13276 /*
13277  * e2fsck.c - superblock checks
13278  */
13279
13280 #define MIN_CHECK 1
13281 #define MAX_CHECK 2
13282
13283 static void check_super_value(e2fsck_t ctx, const char *descr,
13284                               unsigned long value, int flags,
13285                               unsigned long min_val, unsigned long max_val)
13286 {
13287         struct          problem_context pctx;
13288
13289         if (((flags & MIN_CHECK) && (value < min_val)) ||
13290             ((flags & MAX_CHECK) && (value > max_val))) {
13291                 clear_problem_context(&pctx);
13292                 pctx.num = value;
13293                 pctx.str = descr;
13294                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
13295                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
13296         }
13297 }
13298
13299 /*
13300  * This routine may get stubbed out in special compilations of the
13301  * e2fsck code..
13302  */
13303 #ifndef EXT2_SPECIAL_DEVICE_SIZE
13304 static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
13305 {
13306         return (ext2fs_get_device_size(ctx->filesystem_name,
13307                                        EXT2_BLOCK_SIZE(ctx->fs->super),
13308                                        &ctx->num_blocks));
13309 }
13310 #endif
13311
13312 /*
13313  * helper function to release an inode
13314  */
13315 struct process_block_struct {
13316         e2fsck_t        ctx;
13317         char            *buf;
13318         struct problem_context *pctx;
13319         int             truncating;
13320         int             truncate_offset;
13321         e2_blkcnt_t     truncate_block;
13322         int             truncated_blocks;
13323         int             abort;
13324         errcode_t       errcode;
13325 };
13326
13327 static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
13328                                e2_blkcnt_t blockcnt,
13329                                blk_t    ref_blk FSCK_ATTR((unused)),
13330                                int      ref_offset FSCK_ATTR((unused)),
13331                                void *priv_data)
13332 {
13333         struct process_block_struct *pb;
13334         e2fsck_t                ctx;
13335         struct problem_context  *pctx;
13336         blk_t                   blk = *block_nr;
13337         int                     retval = 0;
13338
13339         pb = (struct process_block_struct *) priv_data;
13340         ctx = pb->ctx;
13341         pctx = pb->pctx;
13342
13343         pctx->blk = blk;
13344         pctx->blkcount = blockcnt;
13345
13346         if (HOLE_BLKADDR(blk))
13347                 return 0;
13348
13349         if ((blk < fs->super->s_first_data_block) ||
13350             (blk >= fs->super->s_blocks_count)) {
13351                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
13352         return_abort:
13353                 pb->abort = 1;
13354                 return BLOCK_ABORT;
13355         }
13356
13357         if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
13358                 fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
13359                 goto return_abort;
13360         }
13361
13362         /*
13363          * If we are deleting an orphan, then we leave the fields alone.
13364          * If we are truncating an orphan, then update the inode fields
13365          * and clean up any partial block data.
13366          */
13367         if (pb->truncating) {
13368                 /*
13369                  * We only remove indirect blocks if they are
13370                  * completely empty.
13371                  */
13372                 if (blockcnt < 0) {
13373                         int     i, limit;
13374                         blk_t   *bp;
13375
13376                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
13377                                                         pb->buf);
13378                         if (pb->errcode)
13379                                 goto return_abort;
13380
13381                         limit = fs->blocksize >> 2;
13382                         for (i = 0, bp = (blk_t *) pb->buf;
13383                              i < limit;  i++, bp++)
13384                                 if (*bp)
13385                                         return 0;
13386                 }
13387                 /*
13388                  * We don't remove direct blocks until we've reached
13389                  * the truncation block.
13390                  */
13391                 if (blockcnt >= 0 && blockcnt < pb->truncate_block)
13392                         return 0;
13393                 /*
13394                  * If part of the last block needs truncating, we do
13395                  * it here.
13396                  */
13397                 if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
13398                         pb->errcode = io_channel_read_blk(fs->io, blk, 1,
13399                                                         pb->buf);
13400                         if (pb->errcode)
13401                                 goto return_abort;
13402                         memset(pb->buf + pb->truncate_offset, 0,
13403                                fs->blocksize - pb->truncate_offset);
13404                         pb->errcode = io_channel_write_blk(fs->io, blk, 1,
13405                                                          pb->buf);
13406                         if (pb->errcode)
13407                                 goto return_abort;
13408                 }
13409                 pb->truncated_blocks++;
13410                 *block_nr = 0;
13411                 retval |= BLOCK_CHANGED;
13412         }
13413
13414         ext2fs_block_alloc_stats(fs, blk, -1);
13415         return retval;
13416 }
13417
13418 /*
13419  * This function releases an inode.  Returns 1 if an inconsistency was
13420  * found.  If the inode has a link count, then it is being truncated and
13421  * not deleted.
13422  */
13423 static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
13424                                 struct ext2_inode *inode, char *block_buf,
13425                                 struct problem_context *pctx)
13426 {
13427         struct process_block_struct     pb;
13428         ext2_filsys                     fs = ctx->fs;
13429         errcode_t                       retval;
13430         __u32                           count;
13431
13432         if (!ext2fs_inode_has_valid_blocks(inode))
13433                 return 0;
13434
13435         pb.buf = block_buf + 3 * ctx->fs->blocksize;
13436         pb.ctx = ctx;
13437         pb.abort = 0;
13438         pb.errcode = 0;
13439         pb.pctx = pctx;
13440         if (inode->i_links_count) {
13441                 pb.truncating = 1;
13442                 pb.truncate_block = (e2_blkcnt_t)
13443                         ((((long long)inode->i_size_high << 32) +
13444                           inode->i_size + fs->blocksize - 1) /
13445                          fs->blocksize);
13446                 pb.truncate_offset = inode->i_size % fs->blocksize;
13447         } else {
13448                 pb.truncating = 0;
13449                 pb.truncate_block = 0;
13450                 pb.truncate_offset = 0;
13451         }
13452         pb.truncated_blocks = 0;
13453         retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
13454                                       block_buf, release_inode_block, &pb);
13455         if (retval) {
13456                 com_err("release_inode_blocks", retval,
13457                         _("while calling ext2fs_block_iterate for inode %d"),
13458                         ino);
13459                 return 1;
13460         }
13461         if (pb.abort)
13462                 return 1;
13463
13464         /* Refresh the inode since ext2fs_block_iterate may have changed it */
13465         e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
13466
13467         if (pb.truncated_blocks)
13468                 inode->i_blocks -= pb.truncated_blocks *
13469                         (fs->blocksize / 512);
13470
13471         if (inode->i_file_acl) {
13472                 retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
13473                                                    block_buf, -1, &count);
13474                 if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
13475                         retval = 0;
13476                         count = 1;
13477                 }
13478                 if (retval) {
13479                         com_err("release_inode_blocks", retval,
13480                 _("while calling ext2fs_adjust_ea_refocunt for inode %d"),
13481                                 ino);
13482                         return 1;
13483                 }
13484                 if (count == 0)
13485                         ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
13486                 inode->i_file_acl = 0;
13487         }
13488         return 0;
13489 }
13490
13491 /*
13492  * This function releases all of the orphan inodes.  It returns 1 if
13493  * it hit some error, and 0 on success.
13494  */
13495 static int release_orphan_inodes(e2fsck_t ctx)
13496 {
13497         ext2_filsys fs = ctx->fs;
13498         ext2_ino_t      ino, next_ino;
13499         struct ext2_inode inode;
13500         struct problem_context pctx;
13501         char *block_buf;
13502
13503         if ((ino = fs->super->s_last_orphan) == 0)
13504                 return 0;
13505
13506         /*
13507          * Win or lose, we won't be using the head of the orphan inode
13508          * list again.
13509          */
13510         fs->super->s_last_orphan = 0;
13511         ext2fs_mark_super_dirty(fs);
13512
13513         /*
13514          * If the filesystem contains errors, don't run the orphan
13515          * list, since the orphan list can't be trusted; and we're
13516          * going to be running a full e2fsck run anyway...
13517          */
13518         if (fs->super->s_state & EXT2_ERROR_FS)
13519                 return 0;
13520
13521         if ((ino < EXT2_FIRST_INODE(fs->super)) ||
13522             (ino > fs->super->s_inodes_count)) {
13523                 clear_problem_context(&pctx);
13524                 pctx.ino = ino;
13525                 fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
13526                 return 1;
13527         }
13528
13529         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
13530                                                     "block iterate buffer");
13531         e2fsck_read_bitmaps(ctx);
13532
13533         while (ino) {
13534                 e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
13535                 clear_problem_context(&pctx);
13536                 pctx.ino = ino;
13537                 pctx.inode = &inode;
13538                 pctx.str = inode.i_links_count ? _("Truncating") :
13539                         _("Clearing");
13540
13541                 fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
13542
13543                 next_ino = inode.i_dtime;
13544                 if (next_ino &&
13545                     ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
13546                      (next_ino > fs->super->s_inodes_count))) {
13547                         pctx.ino = next_ino;
13548                         fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
13549                         goto return_abort;
13550                 }
13551
13552                 if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
13553                         goto return_abort;
13554
13555                 if (!inode.i_links_count) {
13556                         ext2fs_inode_alloc_stats2(fs, ino, -1,
13557                                                   LINUX_S_ISDIR(inode.i_mode));
13558                         inode.i_dtime = time(0);
13559                 } else {
13560                         inode.i_dtime = 0;
13561                 }
13562                 e2fsck_write_inode(ctx, ino, &inode, "delete_file");
13563                 ino = next_ino;
13564         }
13565         ext2fs_free_mem(&block_buf);
13566         return 0;
13567 return_abort:
13568         ext2fs_free_mem(&block_buf);
13569         return 1;
13570 }
13571
13572 /*
13573  * Check the resize inode to make sure it is sane.  We check both for
13574  * the case where on-line resizing is not enabled (in which case the
13575  * resize inode should be cleared) as well as the case where on-line
13576  * resizing is enabled.
13577  */
13578 static void check_resize_inode(e2fsck_t ctx)
13579 {
13580         ext2_filsys fs = ctx->fs;
13581         struct ext2_inode inode;
13582         struct problem_context  pctx;
13583         int             i, j, gdt_off, ind_off;
13584         blk_t           blk, pblk, expect;
13585         __u32           *dind_buf = 0, *ind_buf;
13586         errcode_t       retval;
13587
13588         clear_problem_context(&pctx);
13589
13590         /*
13591          * If the resize inode feature isn't set, then
13592          * s_reserved_gdt_blocks must be zero.
13593          */
13594         if (!(fs->super->s_feature_compat &
13595               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
13596                 if (fs->super->s_reserved_gdt_blocks) {
13597                         pctx.num = fs->super->s_reserved_gdt_blocks;
13598                         if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
13599                                         &pctx)) {
13600                                 fs->super->s_reserved_gdt_blocks = 0;
13601                                 ext2fs_mark_super_dirty(fs);
13602                         }
13603                 }
13604         }
13605
13606         /* Read the resizde inode */
13607         pctx.ino = EXT2_RESIZE_INO;
13608         retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
13609         if (retval) {
13610                 if (fs->super->s_feature_compat &
13611                     EXT2_FEATURE_COMPAT_RESIZE_INODE)
13612                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
13613                 return;
13614         }
13615
13616         /*
13617          * If the resize inode feature isn't set, check to make sure
13618          * the resize inode is cleared; then we're done.
13619          */
13620         if (!(fs->super->s_feature_compat &
13621               EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
13622                 for (i=0; i < EXT2_N_BLOCKS; i++) {
13623                         if (inode.i_block[i])
13624                                 break;
13625                 }
13626                 if ((i < EXT2_N_BLOCKS) &&
13627                     fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
13628                         memset(&inode, 0, sizeof(inode));
13629                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
13630                                            "clear_resize");
13631                 }
13632                 return;
13633         }
13634
13635         /*
13636          * The resize inode feature is enabled; check to make sure the
13637          * only block in use is the double indirect block
13638          */
13639         blk = inode.i_block[EXT2_DIND_BLOCK];
13640         for (i=0; i < EXT2_N_BLOCKS; i++) {
13641                 if (i != EXT2_DIND_BLOCK && inode.i_block[i])
13642                         break;
13643         }
13644         if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
13645             !(inode.i_mode & LINUX_S_IFREG) ||
13646             (blk < fs->super->s_first_data_block ||
13647              blk >= fs->super->s_blocks_count)) {
13648         resize_inode_invalid:
13649                 if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
13650                         memset(&inode, 0, sizeof(inode));
13651                         e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
13652                                            "clear_resize");
13653                         ctx->flags |= E2F_FLAG_RESIZE_INODE;
13654                 }
13655                 if (!(ctx->options & E2F_OPT_READONLY)) {
13656                         fs->super->s_state &= ~EXT2_VALID_FS;
13657                         ext2fs_mark_super_dirty(fs);
13658                 }
13659                 goto cleanup;
13660         }
13661         dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
13662                                                     "resize dind buffer");
13663         ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
13664
13665         retval = ext2fs_read_ind_block(fs, blk, dind_buf);
13666         if (retval)
13667                 goto resize_inode_invalid;
13668
13669         gdt_off = fs->desc_blocks;
13670         pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
13671         for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
13672              i++, gdt_off++, pblk++) {
13673                 gdt_off %= fs->blocksize/4;
13674                 if (dind_buf[gdt_off] != pblk)
13675                         goto resize_inode_invalid;
13676                 retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
13677                 if (retval)
13678                         goto resize_inode_invalid;
13679                 ind_off = 0;
13680                 for (j = 1; j < fs->group_desc_count; j++) {
13681                         if (!ext2fs_bg_has_super(fs, j))
13682                                 continue;
13683                         expect = pblk + (j * fs->super->s_blocks_per_group);
13684                         if (ind_buf[ind_off] != expect)
13685                                 goto resize_inode_invalid;
13686                         ind_off++;
13687                 }
13688         }
13689
13690 cleanup:
13691         if (dind_buf)
13692                 ext2fs_free_mem(&dind_buf);
13693
13694  }
13695
13696 static void check_super_block(e2fsck_t ctx)
13697 {
13698         ext2_filsys fs = ctx->fs;
13699         blk_t   first_block, last_block;
13700         struct ext2_super_block *sb = fs->super;
13701         struct ext2_group_desc *gd;
13702         blk_t   blocks_per_group = fs->super->s_blocks_per_group;
13703         blk_t   bpg_max;
13704         int     inodes_per_block;
13705         int     ipg_max;
13706         int     inode_size;
13707         dgrp_t  i;
13708         blk_t   should_be;
13709         struct problem_context  pctx;
13710         __u32   free_blocks = 0, free_inodes = 0;
13711
13712         inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
13713         ipg_max = inodes_per_block * (blocks_per_group - 4);
13714         if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
13715                 ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
13716         bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
13717         if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
13718                 bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
13719
13720         ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
13721                  sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
13722         ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
13723                  sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
13724         ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
13725                 sizeof(int) * fs->group_desc_count, "invalid_inode_table");
13726
13727         clear_problem_context(&pctx);
13728
13729         /*
13730          * Verify the super block constants...
13731          */
13732         check_super_value(ctx, "inodes_count", sb->s_inodes_count,
13733                           MIN_CHECK, 1, 0);
13734         check_super_value(ctx, "blocks_count", sb->s_blocks_count,
13735                           MIN_CHECK, 1, 0);
13736         check_super_value(ctx, "first_data_block", sb->s_first_data_block,
13737                           MAX_CHECK, 0, sb->s_blocks_count);
13738         check_super_value(ctx, "log_block_size", sb->s_log_block_size,
13739                           MIN_CHECK | MAX_CHECK, 0,
13740                           EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
13741         check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
13742                           MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
13743         check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
13744                           MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
13745                           bpg_max);
13746         check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
13747                           MIN_CHECK | MAX_CHECK, 8, bpg_max);
13748         check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
13749                           MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
13750         check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
13751                           MAX_CHECK, 0, sb->s_blocks_count / 2);
13752         check_super_value(ctx, "reserved_gdt_blocks",
13753                           sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
13754                           fs->blocksize/4);
13755         inode_size = EXT2_INODE_SIZE(sb);
13756         check_super_value(ctx, "inode_size",
13757                           inode_size, MIN_CHECK | MAX_CHECK,
13758                           EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
13759         if (inode_size & (inode_size - 1)) {
13760                 pctx.num = inode_size;
13761                 pctx.str = "inode_size";
13762                 fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
13763                 ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
13764                 return;
13765         }
13766
13767         if (!ctx->num_blocks) {
13768                 pctx.errcode = e2fsck_get_device_size(ctx);
13769                 if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
13770                         fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
13771                         ctx->flags |= E2F_FLAG_ABORT;
13772                         return;
13773                 }
13774                 if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
13775                     (ctx->num_blocks < sb->s_blocks_count)) {
13776                         pctx.blk = sb->s_blocks_count;
13777                         pctx.blk2 = ctx->num_blocks;
13778                         if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
13779                                 ctx->flags |= E2F_FLAG_ABORT;
13780                                 return;
13781                         }
13782                 }
13783         }
13784
13785         if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
13786                 pctx.blk = EXT2_BLOCK_SIZE(sb);
13787                 pctx.blk2 = EXT2_FRAG_SIZE(sb);
13788                 fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
13789                 ctx->flags |= E2F_FLAG_ABORT;
13790                 return;
13791         }
13792
13793         should_be = sb->s_frags_per_group >>
13794                 (sb->s_log_block_size - sb->s_log_frag_size);
13795         if (sb->s_blocks_per_group != should_be) {
13796                 pctx.blk = sb->s_blocks_per_group;
13797                 pctx.blk2 = should_be;
13798                 fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
13799                 ctx->flags |= E2F_FLAG_ABORT;
13800                 return;
13801         }
13802
13803         should_be = (sb->s_log_block_size == 0) ? 1 : 0;
13804         if (sb->s_first_data_block != should_be) {
13805                 pctx.blk = sb->s_first_data_block;
13806                 pctx.blk2 = should_be;
13807                 fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
13808                 ctx->flags |= E2F_FLAG_ABORT;
13809                 return;
13810         }
13811
13812         should_be = sb->s_inodes_per_group * fs->group_desc_count;
13813         if (sb->s_inodes_count != should_be) {
13814                 pctx.ino = sb->s_inodes_count;
13815                 pctx.ino2 = should_be;
13816                 if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
13817                         sb->s_inodes_count = should_be;
13818                         ext2fs_mark_super_dirty(fs);
13819                 }
13820         }
13821
13822         /*
13823          * Verify the group descriptors....
13824          */
13825         first_block =  sb->s_first_data_block;
13826         last_block = first_block + blocks_per_group;
13827
13828         for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
13829                 pctx.group = i;
13830
13831                 if (i == fs->group_desc_count - 1)
13832                         last_block = sb->s_blocks_count;
13833                 if ((gd->bg_block_bitmap < first_block) ||
13834                     (gd->bg_block_bitmap >= last_block)) {
13835                         pctx.blk = gd->bg_block_bitmap;
13836                         if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
13837                                 gd->bg_block_bitmap = 0;
13838                 }
13839                 if (gd->bg_block_bitmap == 0) {
13840                         ctx->invalid_block_bitmap_flag[i]++;
13841                         ctx->invalid_bitmaps++;
13842                 }
13843                 if ((gd->bg_inode_bitmap < first_block) ||
13844                     (gd->bg_inode_bitmap >= last_block)) {
13845                         pctx.blk = gd->bg_inode_bitmap;
13846                         if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
13847                                 gd->bg_inode_bitmap = 0;
13848                 }
13849                 if (gd->bg_inode_bitmap == 0) {
13850                         ctx->invalid_inode_bitmap_flag[i]++;
13851                         ctx->invalid_bitmaps++;
13852                 }
13853                 if ((gd->bg_inode_table < first_block) ||
13854                     ((gd->bg_inode_table +
13855                       fs->inode_blocks_per_group - 1) >= last_block)) {
13856                         pctx.blk = gd->bg_inode_table;
13857                         if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
13858                                 gd->bg_inode_table = 0;
13859                 }
13860                 if (gd->bg_inode_table == 0) {
13861                         ctx->invalid_inode_table_flag[i]++;
13862                         ctx->invalid_bitmaps++;
13863                 }
13864                 free_blocks += gd->bg_free_blocks_count;
13865                 free_inodes += gd->bg_free_inodes_count;
13866                 first_block += sb->s_blocks_per_group;
13867                 last_block += sb->s_blocks_per_group;
13868
13869                 if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
13870                     (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
13871                     (gd->bg_used_dirs_count > sb->s_inodes_per_group))
13872                         ext2fs_unmark_valid(fs);
13873
13874         }
13875
13876         /*
13877          * Update the global counts from the block group counts.  This
13878          * is needed for an experimental patch which eliminates
13879          * locking the entire filesystem when allocating blocks or
13880          * inodes; if the filesystem is not unmounted cleanly, the
13881          * global counts may not be accurate.
13882          */
13883         if ((free_blocks != sb->s_free_blocks_count) ||
13884             (free_inodes != sb->s_free_inodes_count)) {
13885                 if (ctx->options & E2F_OPT_READONLY)
13886                         ext2fs_unmark_valid(fs);
13887                 else {
13888                         sb->s_free_blocks_count = free_blocks;
13889                         sb->s_free_inodes_count = free_inodes;
13890                         ext2fs_mark_super_dirty(fs);
13891                 }
13892         }
13893
13894         if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
13895             (sb->s_free_inodes_count > sb->s_inodes_count))
13896                 ext2fs_unmark_valid(fs);
13897
13898
13899         /*
13900          * If we have invalid bitmaps, set the error state of the
13901          * filesystem.
13902          */
13903         if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
13904                 sb->s_state &= ~EXT2_VALID_FS;
13905                 ext2fs_mark_super_dirty(fs);
13906         }
13907
13908         clear_problem_context(&pctx);
13909
13910 #ifndef EXT2_SKIP_UUID
13911         /*
13912          * If the UUID field isn't assigned, assign it.
13913          */
13914         if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
13915                 if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
13916                         uuid_generate(sb->s_uuid);
13917                         ext2fs_mark_super_dirty(fs);
13918                         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
13919                 }
13920         }
13921 #endif
13922
13923         /*
13924          * For the Hurd, check to see if the filetype option is set,
13925          * since it doesn't support it.
13926          */
13927         if (!(ctx->options & E2F_OPT_READONLY) &&
13928             fs->super->s_creator_os == EXT2_OS_HURD &&
13929             (fs->super->s_feature_incompat &
13930              EXT2_FEATURE_INCOMPAT_FILETYPE)) {
13931                 if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
13932                         fs->super->s_feature_incompat &=
13933                                 ~EXT2_FEATURE_INCOMPAT_FILETYPE;
13934                         ext2fs_mark_super_dirty(fs);
13935
13936                 }
13937         }
13938
13939         /*
13940          * If we have any of the compatibility flags set, we need to have a
13941          * revision 1 filesystem.  Most kernels will not check the flags on
13942          * a rev 0 filesystem and we may have corruption issues because of
13943          * the incompatible changes to the filesystem.
13944          */
13945         if (!(ctx->options & E2F_OPT_READONLY) &&
13946             fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
13947             (fs->super->s_feature_compat ||
13948              fs->super->s_feature_ro_compat ||
13949              fs->super->s_feature_incompat) &&
13950             fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
13951                 ext2fs_update_dynamic_rev(fs);
13952                 ext2fs_mark_super_dirty(fs);
13953         }
13954
13955         check_resize_inode(ctx);
13956
13957         /*
13958          * Clean up any orphan inodes, if present.
13959          */
13960         if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
13961                 fs->super->s_state &= ~EXT2_VALID_FS;
13962                 ext2fs_mark_super_dirty(fs);
13963         }
13964
13965         /*
13966          * Move the ext3 journal file, if necessary.
13967          */
13968         e2fsck_move_ext3_journal(ctx);
13969         return;
13970 }
13971
13972 /*
13973  * swapfs.c --- byte-swap an ext2 filesystem
13974  */
13975
13976 #ifdef ENABLE_SWAPFS
13977
13978 struct swap_block_struct {
13979         ext2_ino_t      ino;
13980         int             isdir;
13981         errcode_t       errcode;
13982         char            *dir_buf;
13983         struct ext2_inode *inode;
13984 };
13985
13986 /*
13987  * This is a helper function for block_iterate.  We mark all of the
13988  * indirect and direct blocks as changed, so that block_iterate will
13989  * write them out.
13990  */
13991 static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
13992                       void *priv_data)
13993 {
13994         errcode_t       retval;
13995
13996         struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
13997
13998         if (sb->isdir && (blockcnt >= 0) && *block_nr) {
13999                 retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
14000                 if (retval) {
14001                         sb->errcode = retval;
14002                         return BLOCK_ABORT;
14003                 }
14004                 retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
14005                 if (retval) {
14006                         sb->errcode = retval;
14007                         return BLOCK_ABORT;
14008                 }
14009         }
14010         if (blockcnt >= 0) {
14011                 if (blockcnt < EXT2_NDIR_BLOCKS)
14012                         return 0;
14013                 return BLOCK_CHANGED;
14014         }
14015         if (blockcnt == BLOCK_COUNT_IND) {
14016                 if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
14017                         return 0;
14018                 return BLOCK_CHANGED;
14019         }
14020         if (blockcnt == BLOCK_COUNT_DIND) {
14021                 if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
14022                         return 0;
14023                 return BLOCK_CHANGED;
14024         }
14025         if (blockcnt == BLOCK_COUNT_TIND) {
14026                 if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
14027                         return 0;
14028                 return BLOCK_CHANGED;
14029         }
14030         return BLOCK_CHANGED;
14031 }
14032
14033 /*
14034  * This function is responsible for byte-swapping all of the indirect,
14035  * block pointers.  It is also responsible for byte-swapping directories.
14036  */
14037 static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
14038                               struct ext2_inode *inode)
14039 {
14040         errcode_t                       retval;
14041         struct swap_block_struct        sb;
14042
14043         sb.ino = ino;
14044         sb.inode = inode;
14045         sb.dir_buf = block_buf + ctx->fs->blocksize*3;
14046         sb.errcode = 0;
14047         sb.isdir = 0;
14048         if (LINUX_S_ISDIR(inode->i_mode))
14049                 sb.isdir = 1;
14050
14051         retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
14052                                       swap_block, &sb);
14053         if (retval) {
14054                 com_err("swap_inode_blocks", retval,
14055                         _("while calling ext2fs_block_iterate"));
14056                 ctx->flags |= E2F_FLAG_ABORT;
14057                 return;
14058         }
14059         if (sb.errcode) {
14060                 com_err("swap_inode_blocks", sb.errcode,
14061                         _("while calling iterator function"));
14062                 ctx->flags |= E2F_FLAG_ABORT;
14063                 return;
14064         }
14065 }
14066
14067 static void swap_inodes(e2fsck_t ctx)
14068 {
14069         ext2_filsys fs = ctx->fs;
14070         dgrp_t                  group;
14071         unsigned int            i;
14072         ext2_ino_t              ino = 1;
14073         char                    *buf, *block_buf;
14074         errcode_t               retval;
14075         struct ext2_inode *     inode;
14076
14077         e2fsck_use_inode_shortcuts(ctx, 1);
14078
14079         retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
14080                                 &buf);
14081         if (retval) {
14082                 com_err("swap_inodes", retval,
14083                         _("while allocating inode buffer"));
14084                 ctx->flags |= E2F_FLAG_ABORT;
14085                 return;
14086         }
14087         block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
14088                                                     "block interate buffer");
14089         for (group = 0; group < fs->group_desc_count; group++) {
14090                 retval = io_channel_read_blk(fs->io,
14091                       fs->group_desc[group].bg_inode_table,
14092                       fs->inode_blocks_per_group, buf);
14093                 if (retval) {
14094                         com_err("swap_inodes", retval,
14095                                 _("while reading inode table (group %d)"),
14096                                 group);
14097                         ctx->flags |= E2F_FLAG_ABORT;
14098                         return;
14099                 }
14100                 inode = (struct ext2_inode *) buf;
14101                 for (i=0; i < fs->super->s_inodes_per_group;
14102                      i++, ino++, inode++) {
14103                         ctx->stashed_ino = ino;
14104                         ctx->stashed_inode = inode;
14105
14106                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
14107                                 ext2fs_swap_inode(fs, inode, inode, 0);
14108
14109                         /*
14110                          * Skip deleted files.
14111                          */
14112                         if (inode->i_links_count == 0)
14113                                 continue;
14114
14115                         if (LINUX_S_ISDIR(inode->i_mode) ||
14116                             ((inode->i_block[EXT2_IND_BLOCK] ||
14117                               inode->i_block[EXT2_DIND_BLOCK] ||
14118                               inode->i_block[EXT2_TIND_BLOCK]) &&
14119                              ext2fs_inode_has_valid_blocks(inode)))
14120                                 swap_inode_blocks(ctx, ino, block_buf, inode);
14121
14122                         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
14123                                 return;
14124
14125                         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
14126                                 ext2fs_swap_inode(fs, inode, inode, 1);
14127                 }
14128                 retval = io_channel_write_blk(fs->io,
14129                       fs->group_desc[group].bg_inode_table,
14130                       fs->inode_blocks_per_group, buf);
14131                 if (retval) {
14132                         com_err("swap_inodes", retval,
14133                                 _("while writing inode table (group %d)"),
14134                                 group);
14135                         ctx->flags |= E2F_FLAG_ABORT;
14136                         return;
14137                 }
14138         }
14139         ext2fs_free_mem(&buf);
14140         ext2fs_free_mem(&block_buf);
14141         e2fsck_use_inode_shortcuts(ctx, 0);
14142         ext2fs_flush_icache(fs);
14143 }
14144
14145 #if defined(__powerpc__) && defined(EXT2FS_ENABLE_SWAPFS)
14146 /*
14147  * On the PowerPC, the big-endian variant of the ext2 filesystem
14148  * has its bitmaps stored as 32-bit words with bit 0 as the LSB
14149  * of each word.  Thus a bitmap with only bit 0 set would be, as
14150  * a string of bytes, 00 00 00 01 00 ...
14151  * To cope with this, we byte-reverse each word of a bitmap if
14152  * we have a big-endian filesystem, that is, if we are *not*
14153  * byte-swapping other word-sized numbers.
14154  */
14155 #define EXT2_BIG_ENDIAN_BITMAPS
14156 #endif
14157
14158 #ifdef EXT2_BIG_ENDIAN_BITMAPS
14159 static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
14160 {
14161         __u32 *p = (__u32 *) bmap->bitmap;
14162         int n, nbytes = (bmap->end - bmap->start + 7) / 8;
14163
14164         for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
14165                 *p = ext2fs_swab32(*p);
14166 }
14167 #endif
14168
14169
14170 #ifdef ENABLE_SWAPFS
14171 static void swap_filesys(e2fsck_t ctx)
14172 {
14173         ext2_filsys fs = ctx->fs;
14174 #ifdef RESOURCE_TRACK
14175         struct resource_track   rtrack;
14176
14177         init_resource_track(&rtrack);
14178 #endif
14179
14180         if (!(ctx->options & E2F_OPT_PREEN))
14181                 printf(_("Pass 0: Doing byte-swap of filesystem\n"));
14182
14183 #ifdef MTRACE
14184         mtrace_print("Byte swap");
14185 #endif
14186
14187         if (fs->super->s_mnt_count) {
14188                 fprintf(stderr, _("%s: the filesystem must be freshly "
14189                         "checked using fsck\n"
14190                         "and not mounted before trying to "
14191                         "byte-swap it.\n"), ctx->device_name);
14192                 ctx->flags |= E2F_FLAG_ABORT;
14193                 return;
14194         }
14195         if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
14196                 fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
14197                                EXT2_FLAG_SWAP_BYTES_WRITE);
14198                 fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
14199         } else {
14200                 fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
14201                 fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
14202         }
14203         swap_inodes(ctx);
14204         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
14205                 return;
14206         if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
14207                 fs->flags |= EXT2_FLAG_SWAP_BYTES;
14208         fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
14209                        EXT2_FLAG_SWAP_BYTES_WRITE);
14210
14211 #ifdef EXT2_BIG_ENDIAN_BITMAPS
14212         e2fsck_read_bitmaps(ctx);
14213         ext2fs_swap_bitmap(fs->inode_map);
14214         ext2fs_swap_bitmap(fs->block_map);
14215         fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
14216 #endif
14217         fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
14218         ext2fs_flush(fs);
14219         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
14220
14221 #ifdef RESOURCE_TRACK
14222         if (ctx->options & E2F_OPT_TIME2)
14223                 print_resource_track(_("Byte swap"), &rtrack);
14224 #endif
14225 }
14226 #endif  /* ENABLE_SWAPFS */
14227
14228 #endif
14229
14230 /*
14231  * util.c --- miscellaneous utilities
14232  */
14233
14234 #ifdef HAVE_CONIO_H
14235 #undef HAVE_TERMIOS_H
14236 #include <conio.h>
14237 #define read_a_char()   getch()
14238 #else
14239 #ifdef HAVE_TERMIOS_H
14240 #include <termios.h>
14241 #endif
14242 #endif
14243
14244 #if 0
14245 void fatal_error(e2fsck_t ctx, const char *msg)
14246 {
14247         if (msg)
14248                 fprintf (stderr, "e2fsck: %s\n", msg);
14249         if (ctx->fs && ctx->fs->io) {
14250                 if (ctx->fs->io->magic == EXT2_ET_MAGIC_IO_CHANNEL)
14251                         io_channel_flush(ctx->fs->io);
14252                 else
14253                         fprintf(stderr, "e2fsck: io manager magic bad!\n");
14254         }
14255         ctx->flags |= E2F_FLAG_ABORT;
14256         if (ctx->flags & E2F_FLAG_SETJMP_OK)
14257                 longjmp(ctx->abort_loc, 1);
14258         exit(FSCK_ERROR);
14259 }
14260 #endif
14261
14262 void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
14263                              const char *description)
14264 {
14265         void *ret;
14266         char buf[256];
14267
14268 #ifdef DEBUG_ALLOCATE_MEMORY
14269         printf("Allocating %d bytes for %s...\n", size, description);
14270 #endif
14271         ret = malloc(size);
14272         if (!ret) {
14273                 sprintf(buf, "Can't allocate %s\n", description);
14274                 fatal_error(ctx, buf);
14275         }
14276         memset(ret, 0, size);
14277         return ret;
14278 }
14279
14280 static char *string_copy(const char *str, int len)
14281 {
14282         char    *ret;
14283
14284         if (!str)
14285                 return NULL;
14286         if (!len)
14287                 len = strlen(str);
14288         ret = malloc(len+1);
14289         if (ret) {
14290                 strncpy(ret, str, len);
14291                 ret[len] = 0;
14292         }
14293         return ret;
14294 }
14295
14296 #ifndef HAVE_CONIO_H
14297 static int read_a_char(void)
14298 {
14299         char    c;
14300         int     r;
14301         int     fail = 0;
14302
14303         while(1) {
14304                 if (e2fsck_global_ctx &&
14305                     (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
14306                         return 3;
14307                 }
14308                 r = read(0, &c, 1);
14309                 if (r == 1)
14310                         return c;
14311                 if (fail++ > 100)
14312                         break;
14313         }
14314         return EOF;
14315 }
14316 #endif
14317
14318 static int ask_yn(const char * string, int def)
14319 {
14320         int             c;
14321         const char      *defstr;
14322         static const char short_yes[] = "yY";
14323         static const char short_no[] = "nN";
14324
14325 #ifdef HAVE_TERMIOS_H
14326         struct termios  termios, tmp;
14327
14328         tcgetattr (0, &termios);
14329         tmp = termios;
14330         tmp.c_lflag &= ~(ICANON | ECHO);
14331         tmp.c_cc[VMIN] = 1;
14332         tmp.c_cc[VTIME] = 0;
14333         tcsetattr (0, TCSANOW, &tmp);
14334 #endif
14335
14336         if (def == 1)
14337                 defstr = "<y>";
14338         else if (def == 0)
14339                 defstr = "<n>";
14340         else
14341                 defstr = " (y/n)";
14342         printf("%s%s? ", string, defstr);
14343         while (1) {
14344                 fflush (stdout);
14345                 if ((c = read_a_char()) == EOF)
14346                         break;
14347                 if (c == 3) {
14348 #ifdef HAVE_TERMIOS_H
14349                         tcsetattr (0, TCSANOW, &termios);
14350 #endif
14351                         if (e2fsck_global_ctx &&
14352                             e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
14353                                 puts("\n");
14354                                 longjmp(e2fsck_global_ctx->abort_loc, 1);
14355                         }
14356                         puts(_("cancelled!\n"));
14357                         return 0;
14358                 }
14359                 if (strchr(short_yes, (char) c)) {
14360                         def = 1;
14361                         break;
14362                 }
14363                 else if (strchr(short_no, (char) c)) {
14364                         def = 0;
14365                         break;
14366                 }
14367                 else if ((c == ' ' || c == '\n') && (def != -1))
14368                         break;
14369         }
14370         if (def)
14371                 puts("yes\n");
14372         else
14373                 puts ("no\n");
14374 #ifdef HAVE_TERMIOS_H
14375         tcsetattr (0, TCSANOW, &termios);
14376 #endif
14377         return def;
14378 }
14379
14380 int ask (e2fsck_t ctx, const char * string, int def)
14381 {
14382         if (ctx->options & E2F_OPT_NO) {
14383                 printf (_("%s? no\n\n"), string);
14384                 return 0;
14385         }
14386         if (ctx->options & E2F_OPT_YES) {
14387                 printf (_("%s? yes\n\n"), string);
14388                 return 1;
14389         }
14390         if (ctx->options & E2F_OPT_PREEN) {
14391                 printf ("%s? %s\n\n", string, def ? _("yes") : _("no"));
14392                 return def;
14393         }
14394         return ask_yn(string, def);
14395 }
14396
14397 void e2fsck_read_bitmaps(e2fsck_t ctx)
14398 {
14399         ext2_filsys fs = ctx->fs;
14400         errcode_t       retval;
14401
14402         if (ctx->invalid_bitmaps) {
14403                 com_err(ctx->program_name, 0,
14404                     _("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
14405                         ctx->device_name);
14406                 fatal_error(ctx, 0);
14407         }
14408
14409         ehandler_operation(_("reading inode and block bitmaps"));
14410         retval = ext2fs_read_bitmaps(fs);
14411         ehandler_operation(0);
14412         if (retval) {
14413                 com_err(ctx->program_name, retval,
14414                         _("while retrying to read bitmaps for %s"),
14415                         ctx->device_name);
14416                 fatal_error(ctx, 0);
14417         }
14418 }
14419
14420 static void e2fsck_write_bitmaps(e2fsck_t ctx)
14421 {
14422         ext2_filsys fs = ctx->fs;
14423         errcode_t       retval;
14424
14425         if (ext2fs_test_bb_dirty(fs)) {
14426                 ehandler_operation(_("writing block bitmaps"));
14427                 retval = ext2fs_write_block_bitmap(fs);
14428                 ehandler_operation(0);
14429                 if (retval) {
14430                         com_err(ctx->program_name, retval,
14431                             _("while retrying to write block bitmaps for %s"),
14432                                 ctx->device_name);
14433                         fatal_error(ctx, 0);
14434                 }
14435         }
14436
14437         if (ext2fs_test_ib_dirty(fs)) {
14438                 ehandler_operation(_("writing inode bitmaps"));
14439                 retval = ext2fs_write_inode_bitmap(fs);
14440                 ehandler_operation(0);
14441                 if (retval) {
14442                         com_err(ctx->program_name, retval,
14443                             _("while retrying to write inode bitmaps for %s"),
14444                                 ctx->device_name);
14445                         fatal_error(ctx, 0);
14446                 }
14447         }
14448 }
14449
14450 void preenhalt(e2fsck_t ctx)
14451 {
14452         ext2_filsys fs = ctx->fs;
14453
14454         if (!(ctx->options & E2F_OPT_PREEN))
14455                 return;
14456         fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
14457                 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
14458                ctx->device_name);
14459         if (fs != NULL) {
14460                 fs->super->s_state |= EXT2_ERROR_FS;
14461                 ext2fs_mark_super_dirty(fs);
14462                 ext2fs_close(fs);
14463         }
14464         exit(FSCK_UNCORRECTED);
14465 }
14466
14467 #ifdef RESOURCE_TRACK
14468 void init_resource_track(struct resource_track *track)
14469 {
14470 #ifdef HAVE_GETRUSAGE
14471         struct rusage r;
14472 #endif
14473
14474         track->brk_start = sbrk(0);
14475         gettimeofday(&track->time_start, 0);
14476 #ifdef HAVE_GETRUSAGE
14477 #ifdef sun
14478         memset(&r, 0, sizeof(struct rusage));
14479 #endif
14480         getrusage(RUSAGE_SELF, &r);
14481         track->user_start = r.ru_utime;
14482         track->system_start = r.ru_stime;
14483 #else
14484         track->user_start.tv_sec = track->user_start.tv_usec = 0;
14485         track->system_start.tv_sec = track->system_start.tv_usec = 0;
14486 #endif
14487 }
14488
14489 static _INLINE_ float timeval_subtract(struct timeval *tv1,
14490                                        struct timeval *tv2)
14491 {
14492         return ((tv1->tv_sec - tv2->tv_sec) +
14493                 ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
14494 }
14495
14496 void print_resource_track(const char *desc, struct resource_track *track)
14497 {
14498 #ifdef HAVE_GETRUSAGE
14499         struct rusage r;
14500 #endif
14501 #ifdef HAVE_MALLINFO
14502         struct mallinfo malloc_info;
14503 #endif
14504         struct timeval time_end;
14505
14506         gettimeofday(&time_end, 0);
14507
14508         if (desc)
14509                 printf("%s: ", desc);
14510
14511 #ifdef HAVE_MALLINFO
14512 #define kbytes(x)       (((x) + 1023) / 1024)
14513
14514         malloc_info = mallinfo();
14515         printf(_("Memory used: %dk/%dk (%dk/%dk), "),
14516                kbytes(malloc_info.arena), kbytes(malloc_info.hblkhd),
14517                kbytes(malloc_info.uordblks), kbytes(malloc_info.fordblks));
14518 #else
14519         printf(_("Memory used: %d, "),
14520                (int) (((char *) sbrk(0)) - ((char *) track->brk_start)));
14521 #endif
14522 #ifdef HAVE_GETRUSAGE
14523         getrusage(RUSAGE_SELF, &r);
14524
14525         printf(_("time: %5.2f/%5.2f/%5.2f\n"),
14526                timeval_subtract(&time_end, &track->time_start),
14527                timeval_subtract(&r.ru_utime, &track->user_start),
14528                timeval_subtract(&r.ru_stime, &track->system_start));
14529 #else
14530         printf(_("elapsed time: %6.3f\n"),
14531                timeval_subtract(&time_end, &track->time_start));
14532 #endif
14533 }
14534 #endif /* RESOURCE_TRACK */
14535
14536 void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
14537                               struct ext2_inode * inode, const char *proc)
14538 {
14539         int retval;
14540
14541         retval = ext2fs_read_inode(ctx->fs, ino, inode);
14542         if (retval) {
14543                 com_err("ext2fs_read_inode", retval,
14544                         _("while reading inode %ld in %s"), ino, proc);
14545                 fatal_error(ctx, 0);
14546         }
14547 }
14548
14549 extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
14550                                struct ext2_inode * inode, int bufsize,
14551                                const char *proc)
14552 {
14553         int retval;
14554
14555         retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
14556         if (retval) {
14557                 com_err("ext2fs_write_inode", retval,
14558                         _("while writing inode %ld in %s"), ino, proc);
14559                 fatal_error(ctx, 0);
14560         }
14561 }
14562
14563 extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
14564                                struct ext2_inode * inode, const char *proc)
14565 {
14566         int retval;
14567
14568         retval = ext2fs_write_inode(ctx->fs, ino, inode);
14569         if (retval) {
14570                 com_err("ext2fs_write_inode", retval,
14571                         _("while writing inode %ld in %s"), ino, proc);
14572                 fatal_error(ctx, 0);
14573         }
14574 }
14575
14576 #ifdef MTRACE
14577 void mtrace_print(char *mesg)
14578 {
14579         FILE    *malloc_get_mallstream();
14580         FILE    *f = malloc_get_mallstream();
14581
14582         if (f)
14583                 fprintf(f, "============= %s\n", mesg);
14584 }
14585 #endif
14586
14587 blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
14588                    io_manager manager)
14589 {
14590         struct ext2_super_block *sb;
14591         io_channel              io = NULL;
14592         void                    *buf = NULL;
14593         int                     blocksize;
14594         blk_t                   superblock, ret_sb = 8193;
14595
14596         if (fs && fs->super) {
14597                 ret_sb = (fs->super->s_blocks_per_group +
14598                           fs->super->s_first_data_block);
14599                 if (ctx) {
14600                         ctx->superblock = ret_sb;
14601                         ctx->blocksize = fs->blocksize;
14602                 }
14603                 return ret_sb;
14604         }
14605
14606         if (ctx) {
14607                 if (ctx->blocksize) {
14608                         ret_sb = ctx->blocksize * 8;
14609                         if (ctx->blocksize == 1024)
14610                                 ret_sb++;
14611                         ctx->superblock = ret_sb;
14612                         return ret_sb;
14613                 }
14614                 ctx->superblock = ret_sb;
14615                 ctx->blocksize = 1024;
14616         }
14617
14618         if (!name || !manager)
14619                 goto cleanup;
14620
14621         if (manager->open(name, 0, &io) != 0)
14622                 goto cleanup;
14623
14624         if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
14625                 goto cleanup;
14626         sb = (struct ext2_super_block *) buf;
14627
14628         for (blocksize = EXT2_MIN_BLOCK_SIZE;
14629              blocksize <= EXT2_MAX_BLOCK_SIZE ; blocksize *= 2) {
14630                 superblock = blocksize*8;
14631                 if (blocksize == 1024)
14632                         superblock++;
14633                 io_channel_set_blksize(io, blocksize);
14634                 if (io_channel_read_blk(io, superblock,
14635                                         -SUPERBLOCK_SIZE, buf))
14636                         continue;
14637 #ifdef EXT2FS_ENABLE_SWAPFS
14638                 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
14639                         ext2fs_swap_super(sb);
14640 #endif
14641                 if (sb->s_magic == EXT2_SUPER_MAGIC) {
14642                         ret_sb = superblock;
14643                         if (ctx) {
14644                                 ctx->superblock = superblock;
14645                                 ctx->blocksize = blocksize;
14646                         }
14647                         break;
14648                 }
14649         }
14650
14651 cleanup:
14652         if (io)
14653                 io_channel_close(io);
14654         if (buf)
14655                 ext2fs_free_mem(&buf);
14656         return (ret_sb);
14657 }
14658
14659
14660 /*
14661  * This function runs through the e2fsck passes and calls them all,
14662  * returning restart, abort, or cancel as necessary...
14663  */
14664 typedef void (*pass_t)(e2fsck_t ctx);
14665
14666 static const pass_t e2fsck_passes[] = {
14667         e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
14668         e2fsck_pass5, 0 };
14669
14670 #define E2F_FLAG_RUN_RETURN     (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
14671
14672 static int e2fsck_run(e2fsck_t ctx)
14673 {
14674         int     i;
14675         pass_t  e2fsck_pass;
14676
14677         if (setjmp(ctx->abort_loc)) {
14678                 ctx->flags &= ~E2F_FLAG_SETJMP_OK;
14679                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
14680         }
14681         ctx->flags |= E2F_FLAG_SETJMP_OK;
14682
14683         for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
14684                 if (ctx->flags & E2F_FLAG_RUN_RETURN)
14685                         break;
14686                 e2fsck_pass(ctx);
14687                 if (ctx->progress)
14688                         (void) (ctx->progress)(ctx, 0, 0, 0);
14689         }
14690         ctx->flags &= ~E2F_FLAG_SETJMP_OK;
14691
14692         if (ctx->flags & E2F_FLAG_RUN_RETURN)
14693                 return (ctx->flags & E2F_FLAG_RUN_RETURN);
14694         return 0;
14695 }
14696
14697
14698 /*
14699  * unix.c - The unix-specific code for e2fsck
14700  */
14701
14702
14703 /* Command line options */
14704 static int swapfs;
14705 #ifdef ENABLE_SWAPFS
14706 static int normalize_swapfs;
14707 #endif
14708 static int cflag;               /* check disk */
14709 static int show_version_only;
14710 static int verbose;
14711
14712 static int replace_bad_blocks;
14713 static int keep_bad_blocks;
14714 static char *bad_blocks_file;
14715
14716 #ifdef __CONFIG_JBD_DEBUG__E2FS         /* Enabled by configure --enable-jfs-debug */
14717 int journal_enable_debug = -1;
14718 #endif
14719
14720 #if 0
14721 static void usage(e2fsck_t ctx)
14722 {
14723         fprintf(stderr,
14724                 _("Usage: %s [-panyrcdfvstDFSV] [-b superblock] [-B blocksize]\n"
14725                 "\t\t[-I inode_buffer_blocks] [-P process_inode_size]\n"
14726                 "\t\t[-l|-L bad_blocks_file] [-C fd] [-j ext-journal]\n"
14727                 "\t\t[-E extended-options] device\n"),
14728                 ctx->program_name);
14729
14730         fprintf(stderr, _("\nEmergency help:\n"
14731                 " -p                   Automatic repair (no questions)\n"
14732                 " -n                   Make no changes to the filesystem\n"
14733                 " -y                   Assume \"yes\" to all questions\n"
14734                 " -c                   Check for bad blocks and add them to the badblock list\n"
14735                 " -f                   Force checking even if filesystem is marked clean\n"));
14736         fprintf(stderr, _(""
14737                 " -v                   Be verbose\n"
14738                 " -b superblock        Use alternative superblock\n"
14739                 " -B blocksize         Force blocksize when looking for superblock\n"
14740                 " -j external-journal  Set location of the external journal\n"
14741                 " -l bad_blocks_file   Add to badblocks list\n"
14742                 " -L bad_blocks_file   Set badblocks list\n"
14743                 ));
14744
14745         exit(FSCK_USAGE);
14746 }
14747 #endif
14748
14749 #define P_E2(singular, plural, n)       n, ((n) == 1 ? singular : plural)
14750
14751 static void show_stats(e2fsck_t ctx)
14752 {
14753         ext2_filsys fs = ctx->fs;
14754         int inodes, inodes_used, blocks, blocks_used;
14755         int dir_links;
14756         int num_files, num_links;
14757         int frag_percent;
14758
14759         dir_links = 2 * ctx->fs_directory_count - 1;
14760         num_files = ctx->fs_total_count - dir_links;
14761         num_links = ctx->fs_links_count - dir_links;
14762         inodes = fs->super->s_inodes_count;
14763         inodes_used = (fs->super->s_inodes_count -
14764                        fs->super->s_free_inodes_count);
14765         blocks = fs->super->s_blocks_count;
14766         blocks_used = (fs->super->s_blocks_count -
14767                        fs->super->s_free_blocks_count);
14768
14769         frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
14770         frag_percent = (frag_percent + 5) / 10;
14771
14772         if (!verbose) {
14773                 printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
14774                        ctx->device_name, inodes_used, inodes,
14775                        frag_percent / 10, frag_percent % 10,
14776                        blocks_used, blocks);
14777                 return;
14778         }
14779         printf ("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
14780                 100 * inodes_used / inodes);
14781         printf ("%8d non-contiguous inode%s (%0d.%d%%)\n",
14782                 P_E2("", "s", ctx->fs_fragmented),
14783                 frag_percent / 10, frag_percent % 10);
14784         printf (_("         # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
14785                 ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
14786         printf ("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
14787                 (int) ((long long) 100 * blocks_used / blocks));
14788         printf ("%8d bad block%s\n", P_E2("", "s", ctx->fs_badblocks_count));
14789         printf ("%8d large file%s\n", P_E2("", "s", ctx->large_files));
14790         printf ("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
14791         printf ("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
14792         printf ("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
14793         printf ("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
14794         printf ("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
14795         printf ("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
14796         printf ("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
14797         printf (" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
14798         printf ("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
14799         printf ("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
14800 }
14801
14802 static void check_mount(e2fsck_t ctx)
14803 {
14804         errcode_t       retval;
14805         int             cont;
14806
14807         retval = ext2fs_check_if_mounted(ctx->filesystem_name,
14808                                          &ctx->mount_flags);
14809         if (retval) {
14810                 com_err("ext2fs_check_if_mount", retval,
14811                         _("while determining whether %s is mounted."),
14812                         ctx->filesystem_name);
14813                 return;
14814         }
14815
14816         /*
14817          * If the filesystem isn't mounted, or it's the root filesystem
14818          * and it's mounted read-only, then everything's fine.
14819          */
14820         if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
14821             ((ctx->mount_flags & EXT2_MF_ISROOT) &&
14822              (ctx->mount_flags & EXT2_MF_READONLY)))
14823                 return;
14824
14825         if (ctx->options & E2F_OPT_READONLY) {
14826                 printf(_("Warning!  %s is mounted.\n"), ctx->filesystem_name);
14827                 return;
14828         }
14829
14830         printf(_("%s is mounted.  "), ctx->filesystem_name);
14831         if (!ctx->interactive)
14832                 fatal_error(ctx, _("Cannot continue, aborting.\n\n"));
14833         printf(_("\n\n\007\007\007\007WARNING!!!  "
14834                "Running e2fsck on a mounted filesystem may cause\n"
14835                "SEVERE filesystem damage.\007\007\007\n\n"));
14836         cont = ask_yn(_("Do you really want to continue"), -1);
14837         if (!cont) {
14838                 printf (_("check aborted.\n"));
14839                 exit (0);
14840         }
14841         return;
14842 }
14843
14844 static int is_on_batt(void)
14845 {
14846         FILE    *f;
14847         DIR     *d;
14848         char    tmp[80], tmp2[80], fname[80];
14849         unsigned int    acflag;
14850         struct dirent*  de;
14851
14852         f = fopen("/proc/apm", "r");
14853         if (f) {
14854                 if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
14855                         acflag = 1;
14856                 fclose(f);
14857                 return (acflag != 1);
14858         }
14859         d = opendir("/proc/acpi/ac_adapter");
14860         if (d) {
14861                 while ((de=readdir(d)) != NULL) {
14862                         if (!strncmp(".", de->d_name, 1))
14863                                 continue;
14864                         snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
14865                                  de->d_name);
14866                         f = fopen(fname, "r");
14867                         if (!f)
14868                                 continue;
14869                         if (fscanf(f, "%s %s", tmp2, tmp) != 2)
14870                                 tmp[0] = 0;
14871                         fclose(f);
14872                         if (strncmp(tmp, "off-line", 8) == 0) {
14873                                 closedir(d);
14874                                 return 1;
14875                         }
14876                 }
14877                 closedir(d);
14878         }
14879         return 0;
14880 }
14881
14882 /*
14883  * This routine checks to see if a filesystem can be skipped; if so,
14884  * it will exit with E2FSCK_OK.  Under some conditions it will print a
14885  * message explaining why a check is being forced.
14886  */
14887 static void check_if_skip(e2fsck_t ctx)
14888 {
14889         ext2_filsys fs = ctx->fs;
14890         const char *reason = NULL;
14891         unsigned int reason_arg = 0;
14892         long next_check;
14893         int batt = is_on_batt();
14894         time_t now = time(0);
14895
14896         if ((ctx->options & E2F_OPT_FORCE) || bad_blocks_file ||
14897             cflag || swapfs)
14898                 return;
14899
14900         if ((fs->super->s_state & EXT2_ERROR_FS) ||
14901             !ext2fs_test_valid(fs))
14902                 reason = _(" contains a file system with errors");
14903         else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
14904                 reason = _(" was not cleanly unmounted");
14905         else if ((fs->super->s_max_mnt_count > 0) &&
14906                  (fs->super->s_mnt_count >=
14907                   (unsigned) fs->super->s_max_mnt_count)) {
14908                 reason = _(" has been mounted %u times without being checked");
14909                 reason_arg = fs->super->s_mnt_count;
14910                 if (batt && (fs->super->s_mnt_count <
14911                              (unsigned) fs->super->s_max_mnt_count*2))
14912                         reason = 0;
14913         } else if (fs->super->s_checkinterval &&
14914                    ((now - fs->super->s_lastcheck) >=
14915                     fs->super->s_checkinterval)) {
14916                 reason = _(" has gone %u days without being checked");
14917                 reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
14918                 if (batt && ((now - fs->super->s_lastcheck) <
14919                              fs->super->s_checkinterval*2))
14920                         reason = 0;
14921         }
14922         if (reason) {
14923                 fputs(ctx->device_name, stdout);
14924                 printf(reason, reason_arg);
14925                 fputs(_(", check forced.\n"), stdout);
14926                 return;
14927         }
14928         printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
14929                fs->super->s_inodes_count - fs->super->s_free_inodes_count,
14930                fs->super->s_inodes_count,
14931                fs->super->s_blocks_count - fs->super->s_free_blocks_count,
14932                fs->super->s_blocks_count);
14933         next_check = 100000;
14934         if (fs->super->s_max_mnt_count > 0) {
14935                 next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
14936                 if (next_check <= 0)
14937                         next_check = 1;
14938         }
14939         if (fs->super->s_checkinterval &&
14940             ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
14941                 next_check = 1;
14942         if (next_check <= 5) {
14943                 if (next_check == 1)
14944                         fputs(_(" (check after next mount)"), stdout);
14945                 else
14946                         printf(_(" (check in %ld mounts)"), next_check);
14947         }
14948         fputc('\n', stdout);
14949         ext2fs_close(fs);
14950         ctx->fs = NULL;
14951         e2fsck_free_context(ctx);
14952         exit(FSCK_OK);
14953 }
14954
14955 /*
14956  * For completion notice
14957  */
14958 struct percent_tbl {
14959         int     max_pass;
14960         int     table[32];
14961 };
14962 static const struct percent_tbl e2fsck_tbl = {
14963         5, { 0, 70, 90, 92,  95, 100 }
14964 };
14965
14966 static char bar[128], spaces[128];
14967
14968 static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
14969                           int max)
14970 {
14971         float   percent;
14972
14973         if (pass <= 0)
14974                 return 0.0;
14975         if (pass > tbl->max_pass || max == 0)
14976                 return 100.0;
14977         percent = ((float) curr) / ((float) max);
14978         return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
14979                 + tbl->table[pass-1]);
14980 }
14981
14982 extern void e2fsck_clear_progbar(e2fsck_t ctx)
14983 {
14984         if (!(ctx->flags & E2F_FLAG_PROG_BAR))
14985                 return;
14986
14987         printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
14988                ctx->stop_meta);
14989         fflush(stdout);
14990         ctx->flags &= ~E2F_FLAG_PROG_BAR;
14991 }
14992
14993 int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
14994                            unsigned int dpynum)
14995 {
14996         static const char spinner[] = "\\|/-";
14997         int     i;
14998         unsigned int    tick;
14999         struct timeval  tv;
15000         int dpywidth;
15001         int fixed_percent;
15002
15003         if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
15004                 return 0;
15005
15006         /*
15007          * Calculate the new progress position.  If the
15008          * percentage hasn't changed, then we skip out right
15009          * away.
15010          */
15011         fixed_percent = (int) ((10 * percent) + 0.5);
15012         if (ctx->progress_last_percent == fixed_percent)
15013                 return 0;
15014         ctx->progress_last_percent = fixed_percent;
15015
15016         /*
15017          * If we've already updated the spinner once within
15018          * the last 1/8th of a second, no point doing it
15019          * again.
15020          */
15021         gettimeofday(&tv, NULL);
15022         tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
15023         if ((tick == ctx->progress_last_time) &&
15024             (fixed_percent != 0) && (fixed_percent != 1000))
15025                 return 0;
15026         ctx->progress_last_time = tick;
15027
15028         /*
15029          * Advance the spinner, and note that the progress bar
15030          * will be on the screen
15031          */
15032         ctx->progress_pos = (ctx->progress_pos+1) & 3;
15033         ctx->flags |= E2F_FLAG_PROG_BAR;
15034
15035         dpywidth = 66 - strlen(label);
15036         dpywidth = 8 * (dpywidth / 8);
15037         if (dpynum)
15038                 dpywidth -= 8;
15039
15040         i = ((percent * dpywidth) + 50) / 100;
15041         printf("%s%s: |%s%s", ctx->start_meta, label,
15042                bar + (sizeof(bar) - (i+1)),
15043                spaces + (sizeof(spaces) - (dpywidth - i + 1)));
15044         if (fixed_percent == 1000)
15045                 fputc('|', stdout);
15046         else
15047                 fputc(spinner[ctx->progress_pos & 3], stdout);
15048         printf(" %4.1f%%  ", percent);
15049         if (dpynum)
15050                 printf("%u\r", dpynum);
15051         else
15052                 fputs(" \r", stdout);
15053         fputs(ctx->stop_meta, stdout);
15054
15055         if (fixed_percent == 1000)
15056                 e2fsck_clear_progbar(ctx);
15057         fflush(stdout);
15058
15059         return 0;
15060 }
15061
15062 static int e2fsck_update_progress(e2fsck_t ctx, int pass,
15063                                   unsigned long cur, unsigned long max)
15064 {
15065         char buf[80];
15066         float percent;
15067
15068         if (pass == 0)
15069                 return 0;
15070
15071         if (ctx->progress_fd) {
15072                 sprintf(buf, "%d %lu %lu\n", pass, cur, max);
15073                 write(ctx->progress_fd, buf, strlen(buf));
15074         } else {
15075                 percent = calc_percent(&e2fsck_tbl, pass, cur, max);
15076                 e2fsck_simple_progress(ctx, ctx->device_name,
15077                                        percent, 0);
15078         }
15079         return 0;
15080 }
15081
15082 #define PATH_SET "PATH=/sbin"
15083
15084 static void reserve_stdio_fds(void)
15085 {
15086         int     fd;
15087
15088         while (1) {
15089                 fd = open("/dev/null", O_RDWR);
15090                 if (fd > 2)
15091                         break;
15092                 if (fd < 0) {
15093                         fprintf(stderr, _("ERROR: Couldn't open "
15094                                 "/dev/null (%s)\n"),
15095                                 strerror(errno));
15096                         break;
15097                 }
15098         }
15099         close(fd);
15100 }
15101
15102 static void signal_progress_on(int sig FSCK_ATTR((unused)))
15103 {
15104         e2fsck_t ctx = e2fsck_global_ctx;
15105
15106         if (!ctx)
15107                 return;
15108
15109         ctx->progress = e2fsck_update_progress;
15110         ctx->progress_fd = 0;
15111 }
15112
15113 static void signal_progress_off(int sig FSCK_ATTR((unused)))
15114 {
15115         e2fsck_t ctx = e2fsck_global_ctx;
15116
15117         if (!ctx)
15118                 return;
15119
15120         e2fsck_clear_progbar(ctx);
15121         ctx->progress = 0;
15122 }
15123
15124 static void signal_cancel(int sig FSCK_ATTR((unused)))
15125 {
15126         e2fsck_t ctx = e2fsck_global_ctx;
15127
15128         if (!ctx)
15129                 exit(FSCK_CANCELED);
15130
15131         ctx->flags |= E2F_FLAG_CANCEL;
15132 }
15133
15134 static void parse_extended_opts(e2fsck_t ctx, const char *opts)
15135 {
15136         char    *buf, *token, *next, *p, *arg;
15137         int     ea_ver;
15138         int     extended_usage = 0;
15139
15140         buf = string_copy(opts, 0);
15141         for (token = buf; token && *token; token = next) {
15142                 p = strchr(token, ',');
15143                 next = 0;
15144                 if (p) {
15145                         *p = 0;
15146                         next = p+1;
15147                 }
15148                 arg = strchr(token, '=');
15149                 if (arg) {
15150                         *arg = 0;
15151                         arg++;
15152                 }
15153                 if (strcmp(token, "ea_ver") == 0) {
15154                         if (!arg) {
15155                                 extended_usage++;
15156                                 continue;
15157                         }
15158                         ea_ver = strtoul(arg, &p, 0);
15159                         if (*p ||
15160                             ((ea_ver != 1) && (ea_ver != 2))) {
15161                                 fprintf(stderr,
15162                                         _("Invalid EA version.\n"));
15163                                 extended_usage++;
15164                                 continue;
15165                         }
15166                         ctx->ext_attr_ver = ea_ver;
15167                 } else
15168                         extended_usage++;
15169         }
15170         if (extended_usage) {
15171                 bb_error_msg_and_die(
15172                         "Extended options are separated by commas, "
15173                         "and may take an argument which\n"
15174                         "is set off by an equals ('=') sign.  "
15175                         "Valid raid options are:\n"
15176                         "\tea_ver=<ea_version (1 or 2)\n\n");
15177         }
15178 }
15179
15180
15181 static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
15182 {
15183         int             flush = 0;
15184         int             c, fd;
15185 #ifdef MTRACE
15186         extern void     *mallwatch;
15187 #endif
15188         e2fsck_t        ctx;
15189         errcode_t       retval;
15190         struct sigaction        sa;
15191         char            *extended_opts = 0;
15192
15193         retval = e2fsck_allocate_context(&ctx);
15194         if (retval)
15195                 return retval;
15196
15197         *ret_ctx = ctx;
15198
15199         setvbuf(stdout, NULL, _IONBF, BUFSIZ);
15200         setvbuf(stderr, NULL, _IONBF, BUFSIZ);
15201         if (isatty(0) && isatty(1)) {
15202                 ctx->interactive = 1;
15203         } else {
15204                 ctx->start_meta[0] = '\001';
15205                 ctx->stop_meta[0] = '\002';
15206         }
15207         memset(bar, '=', sizeof(bar)-1);
15208         memset(spaces, ' ', sizeof(spaces)-1);
15209         blkid_get_cache(&ctx->blkid, NULL);
15210
15211         if (argc && *argv)
15212                 ctx->program_name = *argv;
15213         else
15214                 ctx->program_name = "e2fsck";
15215         while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
15216                 switch (c) {
15217                 case 'C':
15218                         ctx->progress = e2fsck_update_progress;
15219                         ctx->progress_fd = atoi(optarg);
15220                         if (!ctx->progress_fd)
15221                                 break;
15222                         /* Validate the file descriptor to avoid disasters */
15223                         fd = dup(ctx->progress_fd);
15224                         if (fd < 0) {
15225                                 fprintf(stderr,
15226                                 _("Error validating file descriptor %d: %s\n"),
15227                                         ctx->progress_fd,
15228                                         error_message(errno));
15229                                 fatal_error(ctx,
15230                         _("Invalid completion information file descriptor"));
15231                         } else
15232                                 close(fd);
15233                         break;
15234                 case 'D':
15235                         ctx->options |= E2F_OPT_COMPRESS_DIRS;
15236                         break;
15237                 case 'E':
15238                         extended_opts = optarg;
15239                         break;
15240                 case 'p':
15241                 case 'a':
15242                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
15243                         conflict_opt:
15244                                 fatal_error(ctx,
15245         _("Only one the options -p/-a, -n or -y may be specified."));
15246                         }
15247                         ctx->options |= E2F_OPT_PREEN;
15248                         break;
15249                 case 'n':
15250                         if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
15251                                 goto conflict_opt;
15252                         ctx->options |= E2F_OPT_NO;
15253                         break;
15254                 case 'y':
15255                         if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
15256                                 goto conflict_opt;
15257                         ctx->options |= E2F_OPT_YES;
15258                         break;
15259                 case 't':
15260 #ifdef RESOURCE_TRACK
15261                         if (ctx->options & E2F_OPT_TIME)
15262                                 ctx->options |= E2F_OPT_TIME2;
15263                         else
15264                                 ctx->options |= E2F_OPT_TIME;
15265 #else
15266                         fprintf(stderr, _("The -t option is not "
15267                                 "supported on this version of e2fsck.\n"));
15268 #endif
15269                         break;
15270                 case 'c':
15271                         if (cflag++)
15272                                 ctx->options |= E2F_OPT_WRITECHECK;
15273                         ctx->options |= E2F_OPT_CHECKBLOCKS;
15274                         break;
15275                 case 'r':
15276                         /* What we do by default, anyway! */
15277                         break;
15278                 case 'b':
15279                         ctx->use_superblock = atoi(optarg);
15280                         ctx->flags |= E2F_FLAG_SB_SPECIFIED;
15281                         break;
15282                 case 'B':
15283                         ctx->blocksize = atoi(optarg);
15284                         break;
15285                 case 'I':
15286                         ctx->inode_buffer_blocks = atoi(optarg);
15287                         break;
15288                 case 'j':
15289                         ctx->journal_name = string_copy(optarg, 0);
15290                         break;
15291                 case 'P':
15292                         ctx->process_inode_size = atoi(optarg);
15293                         break;
15294                 case 'L':
15295                         replace_bad_blocks++;
15296                 case 'l':
15297                         bad_blocks_file = string_copy(optarg, 0);
15298                         break;
15299                 case 'd':
15300                         ctx->options |= E2F_OPT_DEBUG;
15301                         break;
15302                 case 'f':
15303                         ctx->options |= E2F_OPT_FORCE;
15304                         break;
15305                 case 'F':
15306                         flush = 1;
15307                         break;
15308                 case 'v':
15309                         verbose = 1;
15310                         break;
15311                 case 'V':
15312                         show_version_only = 1;
15313                         break;
15314 #ifdef MTRACE
15315                 case 'M':
15316                         mallwatch = (void *) strtol(optarg, NULL, 0);
15317                         break;
15318 #endif
15319                 case 'N':
15320                         ctx->device_name = optarg;
15321                         break;
15322 #ifdef ENABLE_SWAPFS
15323                 case 's':
15324                         normalize_swapfs = 1;
15325                 case 'S':
15326                         swapfs = 1;
15327                         break;
15328 #else
15329                 case 's':
15330                 case 'S':
15331                         fprintf(stderr, _("Byte-swapping filesystems "
15332                                           "not compiled in this version "
15333                                           "of e2fsck\n"));
15334                         exit(1);
15335 #endif
15336                 case 'k':
15337                         keep_bad_blocks++;
15338                         break;
15339                 default:
15340                         usage();
15341                 }
15342         if (show_version_only)
15343                 return 0;
15344         if (optind != argc - 1)
15345                 usage();
15346         if ((ctx->options & E2F_OPT_NO) && !bad_blocks_file &&
15347             !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
15348                 ctx->options |= E2F_OPT_READONLY;
15349         ctx->io_options = strchr(argv[optind], '?');
15350         if (ctx->io_options)
15351                 *ctx->io_options++ = 0;
15352         ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
15353         if (!ctx->filesystem_name) {
15354                 com_err(ctx->program_name, 0, _("Unable to resolve '%s'"),
15355                         argv[optind]);
15356                 fatal_error(ctx, 0);
15357         }
15358         if (extended_opts)
15359                 parse_extended_opts(ctx, extended_opts);
15360
15361         if (flush) {
15362                 fd = open(ctx->filesystem_name, O_RDONLY, 0);
15363                 if (fd < 0) {
15364                         com_err("open", errno,
15365                                 _("while opening %s for flushing"),
15366                                 ctx->filesystem_name);
15367                         fatal_error(ctx, 0);
15368                 }
15369                 if ((retval = ext2fs_sync_device(fd, 1))) {
15370                         com_err("ext2fs_sync_device", retval,
15371                                 _("while trying to flush %s"),
15372                                 ctx->filesystem_name);
15373                         fatal_error(ctx, 0);
15374                 }
15375                 close(fd);
15376         }
15377 #ifdef ENABLE_SWAPFS
15378         if (swapfs) {
15379                 if (cflag || bad_blocks_file) {
15380                         fprintf(stderr, _("Incompatible options not "
15381                                           "allowed when byte-swapping.\n"));
15382                         exit(FSCK_USAGE);
15383                 }
15384         }
15385 #endif
15386         if (cflag && bad_blocks_file) {
15387                 fprintf(stderr, _("The -c and the -l/-L options may "
15388                                   "not be both used at the same time.\n"));
15389                 exit(FSCK_USAGE);
15390         }
15391         /*
15392          * Set up signal action
15393          */
15394         memset(&sa, 0, sizeof(struct sigaction));
15395         sa.sa_handler = signal_cancel;
15396         sigaction(SIGINT, &sa, 0);
15397         sigaction(SIGTERM, &sa, 0);
15398 #ifdef SA_RESTART
15399         sa.sa_flags = SA_RESTART;
15400 #endif
15401         e2fsck_global_ctx = ctx;
15402         sa.sa_handler = signal_progress_on;
15403         sigaction(SIGUSR1, &sa, 0);
15404         sa.sa_handler = signal_progress_off;
15405         sigaction(SIGUSR2, &sa, 0);
15406
15407         /* Update our PATH to include /sbin if we need to run badblocks  */
15408         if (cflag) {
15409                 char *oldpath = getenv("PATH");
15410                 if (oldpath) {
15411                         char *newpath;
15412
15413                         newpath = (char *) malloc(sizeof (PATH_SET) + 1 +
15414                                                   strlen (oldpath));
15415                         if (!newpath)
15416                                 fatal_error(ctx, "Couldn't malloc() newpath");
15417                         strcpy (newpath, PATH_SET);
15418                         strcat (newpath, ":");
15419                         strcat (newpath, oldpath);
15420                         putenv (newpath);
15421                 } else
15422                         putenv (PATH_SET);
15423         }
15424 #ifdef __CONFIG_JBD_DEBUG__E2FS
15425         if (getenv("E2FSCK_JBD_DEBUG"))
15426                 journal_enable_debug = atoi(getenv("E2FSCK_JBD_DEBUG"));
15427 #endif
15428         return 0;
15429 }
15430
15431 static const char my_ver_string[] = E2FSPROGS_VERSION;
15432 static const char my_ver_date[] = E2FSPROGS_DATE;
15433
15434 int e2fsck_main (int argc, char *argv[])
15435 {
15436         errcode_t       retval;
15437         int             exit_value = FSCK_OK;
15438         ext2_filsys     fs = 0;
15439         io_manager      io_ptr;
15440         struct ext2_super_block *sb;
15441         const char      *lib_ver_date;
15442         int             my_ver, lib_ver;
15443         e2fsck_t        ctx;
15444         struct problem_context pctx;
15445         int flags, run_result;
15446
15447         clear_problem_context(&pctx);
15448 #ifdef MTRACE
15449         mtrace();
15450 #endif
15451 #ifdef MCHECK
15452         mcheck(0);
15453 #endif
15454 #ifdef ENABLE_NLS
15455         setlocale(LC_MESSAGES, "");
15456         setlocale(LC_CTYPE, "");
15457         bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
15458         textdomain(NLS_CAT_NAME);
15459 #endif
15460         my_ver = ext2fs_parse_version_string(my_ver_string);
15461         lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
15462         if (my_ver > lib_ver) {
15463                 fprintf( stderr, _("Error: ext2fs library version "
15464                         "out of date!\n"));
15465                 show_version_only++;
15466         }
15467
15468         retval = PRS(argc, argv, &ctx);
15469         if (retval) {
15470                 com_err("e2fsck", retval,
15471                         _("while trying to initialize program"));
15472                 exit(FSCK_ERROR);
15473         }
15474         reserve_stdio_fds();
15475
15476 #ifdef RESOURCE_TRACK
15477         init_resource_track(&ctx->global_rtrack);
15478 #endif
15479
15480         if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
15481                 fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
15482                          my_ver_date);
15483
15484         if (show_version_only) {
15485                 fprintf(stderr, _("\tUsing %s, %s\n"),
15486                         error_message(EXT2_ET_BASE), lib_ver_date);
15487                 exit(FSCK_OK);
15488         }
15489
15490         check_mount(ctx);
15491
15492         if (!(ctx->options & E2F_OPT_PREEN) &&
15493             !(ctx->options & E2F_OPT_NO) &&
15494             !(ctx->options & E2F_OPT_YES)) {
15495                 if (!ctx->interactive)
15496                         fatal_error(ctx,
15497                                     _("need terminal for interactive repairs"));
15498         }
15499         ctx->superblock = ctx->use_superblock;
15500 restart:
15501 #ifdef CONFIG_TESTIO_DEBUG
15502         io_ptr = test_io_manager;
15503         test_io_backing_manager = unix_io_manager;
15504 #else
15505         io_ptr = unix_io_manager;
15506 #endif
15507         flags = 0;
15508         if ((ctx->options & E2F_OPT_READONLY) == 0)
15509                 flags |= EXT2_FLAG_RW;
15510
15511         if (ctx->superblock && ctx->blocksize) {
15512                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
15513                                       flags, ctx->superblock, ctx->blocksize,
15514                                       io_ptr, &fs);
15515         } else if (ctx->superblock) {
15516                 int blocksize;
15517                 for (blocksize = EXT2_MIN_BLOCK_SIZE;
15518                      blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
15519                         retval = ext2fs_open2(ctx->filesystem_name,
15520                                               ctx->io_options, flags,
15521                                               ctx->superblock, blocksize,
15522                                               io_ptr, &fs);
15523                         if (!retval)
15524                                 break;
15525                 }
15526         } else
15527                 retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
15528                                       flags, 0, 0, io_ptr, &fs);
15529         if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
15530             !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
15531             ((retval == EXT2_ET_BAD_MAGIC) ||
15532              ((retval == 0) && ext2fs_check_desc(fs)))) {
15533                 if (!fs || (fs->group_desc_count > 1)) {
15534                         printf(_("%s trying backup blocks...\n"),
15535                                retval ? _("Couldn't find ext2 superblock,") :
15536                                _("Group descriptors look bad..."));
15537                         get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
15538                         if (fs)
15539                                 ext2fs_close(fs);
15540                         goto restart;
15541                 }
15542         }
15543         if (retval) {
15544                 com_err(ctx->program_name, retval, _("while trying to open %s"),
15545                         ctx->filesystem_name);
15546                 if (retval == EXT2_ET_REV_TOO_HIGH) {
15547                         printf(_("The filesystem revision is apparently "
15548                                "too high for this version of e2fsck.\n"
15549                                "(Or the filesystem superblock "
15550                                "is corrupt)\n\n"));
15551                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
15552                 } else if (retval == EXT2_ET_SHORT_READ)
15553                         printf(_("Could this be a zero-length partition?\n"));
15554                 else if ((retval == EPERM) || (retval == EACCES))
15555                         printf(_("You must have %s access to the "
15556                                "filesystem or be root\n"),
15557                                (ctx->options & E2F_OPT_READONLY) ?
15558                                "r/o" : "r/w");
15559                 else if (retval == ENXIO)
15560                         printf(_("Possibly non-existent or swap device?\n"));
15561 #ifdef EROFS
15562                 else if (retval == EROFS)
15563                         printf(_("Disk write-protected; use the -n option "
15564                                "to do a read-only\n"
15565                                "check of the device.\n"));
15566 #endif
15567                 else
15568                         fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
15569                 fatal_error(ctx, 0);
15570         }
15571         ctx->fs = fs;
15572         fs->priv_data = ctx;
15573         sb = fs->super;
15574         if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
15575                 com_err(ctx->program_name, EXT2_ET_REV_TOO_HIGH,
15576                         _("while trying to open %s"),
15577                         ctx->filesystem_name);
15578         get_newer:
15579                 fatal_error(ctx, _("Get a newer version of e2fsck!"));
15580         }
15581
15582         /*
15583          * Set the device name, which is used whenever we print error
15584          * or informational messages to the user.
15585          */
15586         if (ctx->device_name == 0 &&
15587             (sb->s_volume_name[0] != 0)) {
15588                 ctx->device_name = string_copy(sb->s_volume_name,
15589                                                sizeof(sb->s_volume_name));
15590         }
15591         if (ctx->device_name == 0)
15592                 ctx->device_name = ctx->filesystem_name;
15593
15594         /*
15595          * Make sure the ext3 superblock fields are consistent.
15596          */
15597         retval = e2fsck_check_ext3_journal(ctx);
15598         if (retval) {
15599                 com_err(ctx->program_name, retval,
15600                         _("while checking ext3 journal for %s"),
15601                         ctx->device_name);
15602                 fatal_error(ctx, 0);
15603         }
15604
15605         /*
15606          * Check to see if we need to do ext3-style recovery.  If so,
15607          * do it, and then restart the fsck.
15608          */
15609         if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
15610                 if (ctx->options & E2F_OPT_READONLY) {
15611                         printf(_("Warning: skipping journal recovery "
15612                                  "because doing a read-only filesystem "
15613                                  "check.\n"));
15614                         io_channel_flush(ctx->fs->io);
15615                 } else {
15616                         if (ctx->flags & E2F_FLAG_RESTARTED) {
15617                                 /*
15618                                  * Whoops, we attempted to run the
15619                                  * journal twice.  This should never
15620                                  * happen, unless the hardware or
15621                                  * device driver is being bogus.
15622                                  */
15623                                 com_err(ctx->program_name, 0,
15624                                         _("unable to set superblock flags on %s\n"), ctx->device_name);
15625                                 fatal_error(ctx, 0);
15626                         }
15627                         retval = e2fsck_run_ext3_journal(ctx);
15628                         if (retval) {
15629                                 com_err(ctx->program_name, retval,
15630                                 _("while recovering ext3 journal of %s"),
15631                                         ctx->device_name);
15632                                 fatal_error(ctx, 0);
15633                         }
15634                         ext2fs_close(ctx->fs);
15635                         ctx->fs = 0;
15636                         ctx->flags |= E2F_FLAG_RESTARTED;
15637                         goto restart;
15638                 }
15639         }
15640
15641         /*
15642          * Check for compatibility with the feature sets.  We need to
15643          * be more stringent than ext2fs_open().
15644          */
15645         if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
15646             (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
15647                 com_err(ctx->program_name, EXT2_ET_UNSUPP_FEATURE,
15648                         "(%s)", ctx->device_name);
15649                 goto get_newer;
15650         }
15651         if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
15652                 com_err(ctx->program_name, EXT2_ET_RO_UNSUPP_FEATURE,
15653                         "(%s)", ctx->device_name);
15654                 goto get_newer;
15655         }
15656 #ifdef ENABLE_COMPRESSION
15657         if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
15658                 com_err(ctx->program_name, 0,
15659                         _("Warning: compression support is experimental.\n"));
15660 #endif
15661 #ifndef ENABLE_HTREE
15662         if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
15663                 com_err(ctx->program_name, 0,
15664                         _("E2fsck not compiled with HTREE support,\n\t"
15665                           "but filesystem %s has HTREE directories.\n"),
15666                         ctx->device_name);
15667                 goto get_newer;
15668         }
15669 #endif
15670
15671         /*
15672          * If the user specified a specific superblock, presumably the
15673          * master superblock has been trashed.  So we mark the
15674          * superblock as dirty, so it can be written out.
15675          */
15676         if (ctx->superblock &&
15677             !(ctx->options & E2F_OPT_READONLY))
15678                 ext2fs_mark_super_dirty(fs);
15679
15680         /*
15681          * We only update the master superblock because (a) paranoia;
15682          * we don't want to corrupt the backup superblocks, and (b) we
15683          * don't need to update the mount count and last checked
15684          * fields in the backup superblock (the kernel doesn't
15685          * update the backup superblocks anyway).
15686          */
15687         fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
15688
15689         ehandler_init(fs->io);
15690
15691         if (ctx->superblock)
15692                 set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
15693         ext2fs_mark_valid(fs);
15694         check_super_block(ctx);
15695         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15696                 fatal_error(ctx, 0);
15697         check_if_skip(ctx);
15698         if (bad_blocks_file)
15699                 read_bad_blocks_file(ctx, bad_blocks_file, replace_bad_blocks);
15700         else if (cflag)
15701                 read_bad_blocks_file(ctx, 0, !keep_bad_blocks); /* Test disk */
15702         if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15703                 fatal_error(ctx, 0);
15704 #ifdef ENABLE_SWAPFS
15705         if (normalize_swapfs) {
15706                 if ((fs->flags & EXT2_FLAG_SWAP_BYTES) ==
15707                     ext2fs_native_flag()) {
15708                         fprintf(stderr, _("%s: Filesystem byte order "
15709                                 "already normalized.\n"), ctx->device_name);
15710                         fatal_error(ctx, 0);
15711                 }
15712         }
15713         if (swapfs) {
15714                 swap_filesys(ctx);
15715                 if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
15716                         fatal_error(ctx, 0);
15717         }
15718 #endif
15719
15720         /*
15721          * Mark the system as valid, 'til proven otherwise
15722          */
15723         ext2fs_mark_valid(fs);
15724
15725         retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
15726         if (retval) {
15727                 com_err(ctx->program_name, retval,
15728                         _("while reading bad blocks inode"));
15729                 preenhalt(ctx);
15730                 printf(_("This doesn't bode well,"
15731                          " but we'll try to go on...\n"));
15732         }
15733
15734         run_result = e2fsck_run(ctx);
15735         e2fsck_clear_progbar(ctx);
15736         if (run_result == E2F_FLAG_RESTART) {
15737                 printf(_("Restarting e2fsck from the beginning...\n"));
15738                 retval = e2fsck_reset_context(ctx);
15739                 if (retval) {
15740                         com_err(ctx->program_name, retval,
15741                                 _("while resetting context"));
15742                         fatal_error(ctx, 0);
15743                 }
15744                 ext2fs_close(fs);
15745                 goto restart;
15746         }
15747         if (run_result & E2F_FLAG_CANCEL) {
15748                 printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
15749                        ctx->device_name : ctx->filesystem_name);
15750                 exit_value |= FSCK_CANCELED;
15751         }
15752         if (run_result & E2F_FLAG_ABORT)
15753                 fatal_error(ctx, _("aborted"));
15754
15755 #ifdef MTRACE
15756         mtrace_print("Cleanup");
15757 #endif
15758         if (ext2fs_test_changed(fs)) {
15759                 exit_value |= FSCK_NONDESTRUCT;
15760                 if (!(ctx->options & E2F_OPT_PREEN))
15761                     printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
15762                                ctx->device_name);
15763                 if (ctx->mount_flags & EXT2_MF_ISROOT) {
15764                         printf(_("%s: ***** REBOOT LINUX *****\n"),
15765                                ctx->device_name);
15766                         exit_value |= FSCK_REBOOT;
15767                 }
15768         }
15769         if (!ext2fs_test_valid(fs)) {
15770                 printf(_("\n%s: ********** WARNING: Filesystem still has "
15771                          "errors **********\n\n"), ctx->device_name);
15772                 exit_value |= FSCK_UNCORRECTED;
15773                 exit_value &= ~FSCK_NONDESTRUCT;
15774         }
15775         if (exit_value & FSCK_CANCELED)
15776                 exit_value &= ~FSCK_NONDESTRUCT;
15777         else {
15778                 show_stats(ctx);
15779                 if (!(ctx->options & E2F_OPT_READONLY)) {
15780                         if (ext2fs_test_valid(fs)) {
15781                                 if (!(sb->s_state & EXT2_VALID_FS))
15782                                         exit_value |= FSCK_NONDESTRUCT;
15783                                 sb->s_state = EXT2_VALID_FS;
15784                         } else
15785                                 sb->s_state &= ~EXT2_VALID_FS;
15786                         sb->s_mnt_count = 0;
15787                         sb->s_lastcheck = time(NULL);
15788                         ext2fs_mark_super_dirty(fs);
15789                 }
15790         }
15791
15792         e2fsck_write_bitmaps(ctx);
15793
15794         ext2fs_close(fs);
15795         ctx->fs = NULL;
15796         free(ctx->filesystem_name);
15797         free(ctx->journal_name);
15798         e2fsck_free_context(ctx);
15799
15800 #ifdef RESOURCE_TRACK
15801         if (ctx->options & E2F_OPT_TIME)
15802                 print_resource_track(NULL, &ctx->global_rtrack);
15803 #endif
15804
15805         return exit_value;
15806 }