busybox/e2fsprogs/old_e2fsprogs/e2fsck.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * e2fsck
   4 *
   5 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
   6 * Copyright (C) 2006 Garrett Kajmowicz
   7 *
   8 * Dictionary Abstract Data Type
   9 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
  10 * Free Software License:
  11 * All rights are reserved by the author, with the following exceptions:
  12 * Permission is granted to freely reproduce and distribute this software,
  13 * possibly in exchange for a fee, provided that this copyright notice appears
  14 * intact. Permission is also granted to adapt this software to produce
  15 * derivative works, as long as the modified versions carry this copyright
  16 * notice and additional notices stating that the work has been modified.
  17 * This source code may be translated into executable form and incorporated
  18 * into proprietary software; there is no requirement for such software to
  19 * contain a copyright notice related to this source.
  20 *
  21 * linux/fs/recovery  and linux/fs/revoke
  22 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
  23 *
  24 * Copyright 1999-2000 Red Hat Software --- All Rights Reserved
  25 *
  26 * Journal recovery routines for the generic filesystem journaling code;
  27 * part of the ext2fs journaling system.
  28 *
  29 * Licensed under GPLv2 or later, see file License in this tarball for details.
  30 */
  31
  32#ifndef _GNU_SOURCE
  33#define _GNU_SOURCE 1 /* get strnlen() */
  34#endif
  35
  36#include "e2fsck.h"     /*Put all of our defines here to clean things up*/
  37
  38#define _(x) x
  39#define N_(x) x
  40
  41/*
  42 * Procedure declarations
  43 */
  44
  45static void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf);
  46
  47/* pass1.c */
  48static void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool);
  49
  50/* pass2.c */
  51static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
  52                                    ext2_ino_t ino, char *buf);
  53
  54/* pass3.c */
  55static int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t inode);
  56static errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
  57                                         int num, int gauranteed_size);
  58static ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix);
  59static errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino,
  60                                           int adj);
  61
  62/* rehash.c */
  63static void e2fsck_rehash_directories(e2fsck_t ctx);
  64
  65/* util.c */
  66static void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
  67                                    const char *description);
  68static int ask(e2fsck_t ctx, const char * string, int def);
  69static void e2fsck_read_bitmaps(e2fsck_t ctx);
  70static void preenhalt(e2fsck_t ctx);
  71static void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
  72                              struct ext2_inode * inode, const char * proc);
  73static void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
  74                               struct ext2_inode * inode, const char * proc);
  75static blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs,
  76                           const char *name, io_manager manager);
  77
  78/* unix.c */
  79static void e2fsck_clear_progbar(e2fsck_t ctx);
  80static int e2fsck_simple_progress(e2fsck_t ctx, const char *label,
  81                                  float percent, unsigned int dpynum);
  82
  83
  84/*
  85 * problem.h --- e2fsck problem error codes
  86 */
  87
  88typedef __u32 problem_t;
  89
  90struct problem_context {
  91        errcode_t       errcode;
  92        ext2_ino_t      ino, ino2, dir;
  93        struct ext2_inode *inode;
  94        struct ext2_dir_entry *dirent;
  95        blk_t           blk, blk2;
  96        e2_blkcnt_t     blkcount;
  97        int             group;
  98        __u64           num;
  99        const char      *str;
 100};
 101
 102
 103/*
 104 * Function declarations
 105 */
 106static int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx);
 107static int end_problem_latch(e2fsck_t ctx, int mask);
 108static int set_latch_flags(int mask, int setflags, int clearflags);
 109static void clear_problem_context(struct problem_context *ctx);
 110
 111/*
 112 * Dictionary Abstract Data Type
 113 * Copyright (C) 1997 Kaz Kylheku <kaz@ashi.footprints.net>
 114 *
 115 * dict.h v 1.22.2.6 2000/11/13 01:36:44 kaz
 116 * kazlib_1_20
 117 */
 118
 119#ifndef DICT_H
 120#define DICT_H
 121
 122/*
 123 * Blurb for inclusion into C++ translation units
 124 */
 125
 126typedef unsigned long dictcount_t;
 127#define DICTCOUNT_T_MAX ULONG_MAX
 128
 129/*
 130 * The dictionary is implemented as a red-black tree
 131 */
 132
 133typedef enum { dnode_red, dnode_black } dnode_color_t;
 134
 135typedef struct dnode_t {
 136        struct dnode_t *dict_left;
 137        struct dnode_t *dict_right;
 138        struct dnode_t *dict_parent;
 139        dnode_color_t dict_color;
 140        const void *dict_key;
 141        void *dict_data;
 142} dnode_t;
 143
 144typedef int (*dict_comp_t)(const void *, const void *);
 145typedef void (*dnode_free_t)(dnode_t *);
 146
 147typedef struct dict_t {
 148        dnode_t dict_nilnode;
 149        dictcount_t dict_nodecount;
 150        dictcount_t dict_maxcount;
 151        dict_comp_t dict_compare;
 152        dnode_free_t dict_freenode;
 153        int dict_dupes;
 154} dict_t;
 155
 156typedef void (*dnode_process_t)(dict_t *, dnode_t *, void *);
 157
 158typedef struct dict_load_t {
 159        dict_t *dict_dictptr;
 160        dnode_t dict_nilnode;
 161} dict_load_t;
 162
 163#define dict_count(D) ((D)->dict_nodecount)
 164#define dnode_get(N) ((N)->dict_data)
 165#define dnode_getkey(N) ((N)->dict_key)
 166
 167#endif
 168
 169/*
 170 * Compatibility header file for e2fsck which should be included
 171 * instead of linux/jfs.h
 172 *
 173 * Copyright (C) 2000 Stephen C. Tweedie
 174 */
 175
 176/*
 177 * Pull in the definition of the e2fsck context structure
 178 */
 179
 180struct buffer_head {
 181        char            b_data[8192];
 182        e2fsck_t        b_ctx;
 183        io_channel      b_io;
 184        int             b_size;
 185        blk_t           b_blocknr;
 186        int             b_dirty;
 187        int             b_uptodate;
 188        int             b_err;
 189};
 190
 191
 192#define K_DEV_FS        1
 193#define K_DEV_JOURNAL   2
 194
 195#define lock_buffer(bh) do {} while (0)
 196#define unlock_buffer(bh) do {} while (0)
 197#define buffer_req(bh) 1
 198#define do_readahead(journal, start) do {} while (0)
 199
 200static e2fsck_t e2fsck_global_ctx;  /* Try your very best not to use this! */
 201
 202typedef struct {
 203        int     object_length;
 204} kmem_cache_t;
 205
 206#define kmem_cache_alloc(cache,flags) malloc((cache)->object_length)
 207
 208/*
 209 * We use the standard libext2fs portability tricks for inline
 210 * functions.
 211 */
 212
 213static kmem_cache_t * do_cache_create(int len)
 214{
 215        kmem_cache_t *new_cache;
 216
 217        new_cache = xmalloc(sizeof(*new_cache));
 218        new_cache->object_length = len;
 219        return new_cache;
 220}
 221
 222static void do_cache_destroy(kmem_cache_t *cache)
 223{
 224        free(cache);
 225}
 226
 227
 228/*
 229 * Dictionary Abstract Data Type
 230 */
 231
 232
 233/*
 234 * These macros provide short convenient names for structure members,
 235 * which are embellished with dict_ prefixes so that they are
 236 * properly confined to the documented namespace. It's legal for a
 237 * program which uses dict to define, for instance, a macro called ``parent''.
 238 * Such a macro would interfere with the dnode_t struct definition.
 239 * In general, highly portable and reusable C modules which expose their
 240 * structures need to confine structure member names to well-defined spaces.
 241 * The resulting identifiers aren't necessarily convenient to use, nor
 242 * readable, in the implementation, however!
 243 */
 244
 245#define left dict_left
 246#define right dict_right
 247#define parent dict_parent
 248#define color dict_color
 249#define key dict_key
 250#define data dict_data
 251
 252#define nilnode dict_nilnode
 253#define maxcount dict_maxcount
 254#define compare dict_compare
 255#define dupes dict_dupes
 256
 257#define dict_root(D) ((D)->nilnode.left)
 258#define dict_nil(D) (&(D)->nilnode)
 259
 260static void dnode_free(dnode_t *node);
 261
 262/*
 263 * Perform a ``left rotation'' adjustment on the tree.  The given node P and
 264 * its right child C are rearranged so that the P instead becomes the left
 265 * child of C.   The left subtree of C is inherited as the new right subtree
 266 * for P.  The ordering of the keys within the tree is thus preserved.
 267 */
 268
 269static void rotate_left(dnode_t *upper)
 270{
 271        dnode_t *lower, *lowleft, *upparent;
 272
 273        lower = upper->right;
 274        upper->right = lowleft = lower->left;
 275        lowleft->parent = upper;
 276
 277        lower->parent = upparent = upper->parent;
 278
 279        /* don't need to check for root node here because root->parent is
 280           the sentinel nil node, and root->parent->left points back to root */
 281
 282        if (upper == upparent->left) {
 283                upparent->left = lower;
 284        } else {
 285                assert (upper == upparent->right);
 286                upparent->right = lower;
 287        }
 288
 289        lower->left = upper;
 290        upper->parent = lower;
 291}
 292
 293/*
 294 * This operation is the ``mirror'' image of rotate_left. It is
 295 * the same procedure, but with left and right interchanged.
 296 */
 297
 298static void rotate_right(dnode_t *upper)
 299{
 300        dnode_t *lower, *lowright, *upparent;
 301
 302        lower = upper->left;
 303        upper->left = lowright = lower->right;
 304        lowright->parent = upper;
 305
 306        lower->parent = upparent = upper->parent;
 307
 308        if (upper == upparent->right) {
 309                upparent->right = lower;
 310        } else {
 311                assert (upper == upparent->left);
 312                upparent->left = lower;
 313        }
 314
 315        lower->right = upper;
 316        upper->parent = lower;
 317}
 318
 319/*
 320 * Do a postorder traversal of the tree rooted at the specified
 321 * node and free everything under it.  Used by dict_free().
 322 */
 323
 324static void free_nodes(dict_t *dict, dnode_t *node, dnode_t *nil)
 325{
 326        if (node == nil)
 327                return;
 328        free_nodes(dict, node->left, nil);
 329        free_nodes(dict, node->right, nil);
 330        dict->dict_freenode(node);
 331}
 332
 333/*
 334 * Verify that the tree contains the given node. This is done by
 335 * traversing all of the nodes and comparing their pointers to the
 336 * given pointer. Returns 1 if the node is found, otherwise
 337 * returns zero. It is intended for debugging purposes.
 338 */
 339
 340static int verify_dict_has_node(dnode_t *nil, dnode_t *root, dnode_t *node)
 341{
 342        if (root != nil) {
 343                return root == node
 344                        || verify_dict_has_node(nil, root->left, node)
 345                        || verify_dict_has_node(nil, root->right, node);
 346        }
 347        return 0;
 348}
 349
 350
 351/*
 352 * Select a different set of node allocator routines.
 353 */
 354
 355static void dict_set_allocator(dict_t *dict, dnode_free_t fr)
 356{
 357        assert(dict_count(dict) == 0);
 358        dict->dict_freenode = fr;
 359}
 360
 361/*
 362 * Free all the nodes in the dictionary by using the dictionary's
 363 * installed free routine. The dictionary is emptied.
 364 */
 365
 366static void dict_free_nodes(dict_t *dict)
 367{
 368        dnode_t *nil = dict_nil(dict), *root = dict_root(dict);
 369        free_nodes(dict, root, nil);
 370        dict->dict_nodecount = 0;
 371        dict->nilnode.left = &dict->nilnode;
 372        dict->nilnode.right = &dict->nilnode;
 373}
 374
 375/*
 376 * Initialize a user-supplied dictionary object.
 377 */
 378
 379static dict_t *dict_init(dict_t *dict, dictcount_t maxcount, dict_comp_t comp)
 380{
 381        dict->compare = comp;
 382        dict->dict_freenode = dnode_free;
 383        dict->dict_nodecount = 0;
 384        dict->maxcount = maxcount;
 385        dict->nilnode.left = &dict->nilnode;
 386        dict->nilnode.right = &dict->nilnode;
 387        dict->nilnode.parent = &dict->nilnode;
 388        dict->nilnode.color = dnode_black;
 389        dict->dupes = 0;
 390        return dict;
 391}
 392
 393/*
 394 * Locate a node in the dictionary having the given key.
 395 * If the node is not found, a null a pointer is returned (rather than
 396 * a pointer that dictionary's nil sentinel node), otherwise a pointer to the
 397 * located node is returned.
 398 */
 399
 400static dnode_t *dict_lookup(dict_t *dict, const void *key)
 401{
 402        dnode_t *root = dict_root(dict);
 403        dnode_t *nil = dict_nil(dict);
 404        dnode_t *saved;
 405        int result;
 406
 407        /* simple binary search adapted for trees that contain duplicate keys */
 408
 409        while (root != nil) {
 410                result = dict->compare(key, root->key);
 411                if (result < 0)
 412                        root = root->left;
 413                else if (result > 0)
 414                        root = root->right;
 415                else {
 416                        if (!dict->dupes) { /* no duplicates, return match          */
 417                                return root;
 418                        } else {            /* could be dupes, find leftmost one    */
 419                                do {
 420                                        saved = root;
 421                                        root = root->left;
 422                                        while (root != nil && dict->compare(key, root->key))
 423                                                root = root->right;
 424                                } while (root != nil);
 425                                return saved;
 426                        }
 427                }
 428        }
 429
 430        return NULL;
 431}
 432
 433/*
 434 * Insert a node into the dictionary. The node should have been
 435 * initialized with a data field. All other fields are ignored.
 436 * The behavior is undefined if the user attempts to insert into
 437 * a dictionary that is already full (for which the dict_isfull()
 438 * function returns true).
 439 */
 440
 441static void dict_insert(dict_t *dict, dnode_t *node, const void *key)
 442{
 443        dnode_t *where = dict_root(dict), *nil = dict_nil(dict);
 444        dnode_t *parent = nil, *uncle, *grandpa;
 445        int result = -1;
 446
 447        node->key = key;
 448
 449        /* basic binary tree insert */
 450
 451        while (where != nil) {
 452                parent = where;
 453                result = dict->compare(key, where->key);
 454                /* trap attempts at duplicate key insertion unless it's explicitly allowed */
 455                assert(dict->dupes || result != 0);
 456                if (result < 0)
 457                        where = where->left;
 458                else
 459                        where = where->right;
 460        }
 461
 462        assert(where == nil);
 463
 464        if (result < 0)
 465                parent->left = node;
 466        else
 467                parent->right = node;
 468
 469        node->parent = parent;
 470        node->left = nil;
 471        node->right = nil;
 472
 473        dict->dict_nodecount++;
 474
 475        /* red black adjustments */
 476
 477        node->color = dnode_red;
 478
 479        while (parent->color == dnode_red) {
 480                grandpa = parent->parent;
 481                if (parent == grandpa->left) {
 482                        uncle = grandpa->right;
 483                        if (uncle->color == dnode_red) {    /* red parent, red uncle */
 484                                parent->color = dnode_black;
 485                                uncle->color = dnode_black;
 486                                grandpa->color = dnode_red;
 487                                node = grandpa;
 488                                parent = grandpa->parent;
 489                        } else {                            /* red parent, black uncle */
 490                                if (node == parent->right) {
 491                                        rotate_left(parent);
 492                                        parent = node;
 493                                        assert (grandpa == parent->parent);
 494                                        /* rotation between parent and child preserves grandpa */
 495                                }
 496                                parent->color = dnode_black;
 497                                grandpa->color = dnode_red;
 498                                rotate_right(grandpa);
 499                                break;
 500                        }
 501                } else {        /* symmetric cases: parent == parent->parent->right */
 502                        uncle = grandpa->left;
 503                        if (uncle->color == dnode_red) {
 504                                parent->color = dnode_black;
 505                                uncle->color = dnode_black;
 506                                grandpa->color = dnode_red;
 507                                node = grandpa;
 508                                parent = grandpa->parent;
 509                        } else {
 510                                if (node == parent->left) {
 511                                        rotate_right(parent);
 512                                        parent = node;
 513                                        assert (grandpa == parent->parent);
 514                                }
 515                                parent->color = dnode_black;
 516                                grandpa->color = dnode_red;
 517                                rotate_left(grandpa);
 518                                break;
 519                        }
 520                }
 521        }
 522
 523        dict_root(dict)->color = dnode_black;
 524
 525}
 526
 527/*
 528 * Allocate a node using the dictionary's allocator routine, give it
 529 * the data item.
 530 */
 531
 532static dnode_t *dnode_init(dnode_t *dnode, void *data)
 533{
 534        dnode->data = data;
 535        dnode->parent = NULL;
 536        dnode->left = NULL;
 537        dnode->right = NULL;
 538        return dnode;
 539}
 540
 541static int dict_alloc_insert(dict_t *dict, const void *key, void *data)
 542{
 543        dnode_t *node = xmalloc(sizeof(dnode_t));
 544
 545        dnode_init(node, data);
 546        dict_insert(dict, node, key);
 547        return 1;
 548}
 549
 550/*
 551 * Return the node with the lowest (leftmost) key. If the dictionary is empty
 552 * (that is, dict_isempty(dict) returns 1) a null pointer is returned.
 553 */
 554
 555static dnode_t *dict_first(dict_t *dict)
 556{
 557        dnode_t *nil = dict_nil(dict), *root = dict_root(dict), *left;
 558
 559        if (root != nil)
 560                while ((left = root->left) != nil)
 561                        root = left;
 562
 563        return (root == nil) ? NULL : root;
 564}
 565
 566/*
 567 * Return the given node's successor node---the node which has the
 568 * next key in the the left to right ordering. If the node has
 569 * no successor, a null pointer is returned rather than a pointer to
 570 * the nil node.
 571 */
 572
 573static dnode_t *dict_next(dict_t *dict, dnode_t *curr)
 574{
 575        dnode_t *nil = dict_nil(dict), *parent, *left;
 576
 577        if (curr->right != nil) {
 578                curr = curr->right;
 579                while ((left = curr->left) != nil)
 580                        curr = left;
 581                return curr;
 582        }
 583
 584        parent = curr->parent;
 585
 586        while (parent != nil && curr == parent->right) {
 587                curr = parent;
 588                parent = curr->parent;
 589        }
 590
 591        return (parent == nil) ? NULL : parent;
 592}
 593
 594
 595static void dnode_free(dnode_t *node)
 596{
 597        free(node);
 598}
 599
 600
 601#undef left
 602#undef right
 603#undef parent
 604#undef color
 605#undef key
 606#undef data
 607
 608#undef nilnode
 609#undef maxcount
 610#undef compare
 611#undef dupes
 612
 613
 614/*
 615 * dirinfo.c --- maintains the directory information table for e2fsck.
 616 */
 617
 618/*
 619 * This subroutine is called during pass1 to create a directory info
 620 * entry.  During pass1, the passed-in parent is 0; it will get filled
 621 * in during pass2.
 622 */
 623static void e2fsck_add_dir_info(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent)
 624{
 625        struct dir_info *dir;
 626        int             i, j;
 627        ext2_ino_t      num_dirs;
 628        errcode_t       retval;
 629        unsigned long   old_size;
 630
 631        if (!ctx->dir_info) {
 632                ctx->dir_info_count = 0;
 633                retval = ext2fs_get_num_dirs(ctx->fs, &num_dirs);
 634                if (retval)
 635                        num_dirs = 1024;        /* Guess */
 636                ctx->dir_info_size = num_dirs + 10;
 637                ctx->dir_info  = (struct dir_info *)
 638                        e2fsck_allocate_memory(ctx, ctx->dir_info_size
 639                                               * sizeof (struct dir_info),
 640                                               "directory map");
 641        }
 642
 643        if (ctx->dir_info_count >= ctx->dir_info_size) {
 644                old_size = ctx->dir_info_size * sizeof(struct dir_info);
 645                ctx->dir_info_size += 10;
 646                retval = ext2fs_resize_mem(old_size, ctx->dir_info_size *
 647                                           sizeof(struct dir_info),
 648                                           &ctx->dir_info);
 649                if (retval) {
 650                        ctx->dir_info_size -= 10;
 651                        return;
 652                }
 653        }
 654
 655        /*
 656         * Normally, add_dir_info is called with each inode in
 657         * sequential order; but once in a while (like when pass 3
 658         * needs to recreate the root directory or lost+found
 659         * directory) it is called out of order.  In those cases, we
 660         * need to move the dir_info entries down to make room, since
 661         * the dir_info array needs to be sorted by inode number for
 662         * get_dir_info()'s sake.
 663         */
 664        if (ctx->dir_info_count &&
 665            ctx->dir_info[ctx->dir_info_count-1].ino >= ino) {
 666                for (i = ctx->dir_info_count-1; i > 0; i--)
 667                        if (ctx->dir_info[i-1].ino < ino)
 668                                break;
 669                dir = &ctx->dir_info[i];
 670                if (dir->ino != ino)
 671                        for (j = ctx->dir_info_count++; j > i; j--)
 672                                ctx->dir_info[j] = ctx->dir_info[j-1];
 673        } else
 674                dir = &ctx->dir_info[ctx->dir_info_count++];
 675
 676        dir->ino = ino;
 677        dir->dotdot = parent;
 678        dir->parent = parent;
 679}
 680
 681/*
 682 * get_dir_info() --- given an inode number, try to find the directory
 683 * information entry for it.
 684 */
 685static struct dir_info *e2fsck_get_dir_info(e2fsck_t ctx, ext2_ino_t ino)
 686{
 687        int     low, high, mid;
 688
 689        low = 0;
 690        high = ctx->dir_info_count-1;
 691        if (!ctx->dir_info)
 692                return 0;
 693        if (ino == ctx->dir_info[low].ino)
 694                return &ctx->dir_info[low];
 695        if  (ino == ctx->dir_info[high].ino)
 696                return &ctx->dir_info[high];
 697
 698        while (low < high) {
 699                mid = (low+high)/2;
 700                if (mid == low || mid == high)
 701                        break;
 702                if (ino == ctx->dir_info[mid].ino)
 703                        return &ctx->dir_info[mid];
 704                if (ino < ctx->dir_info[mid].ino)
 705                        high = mid;
 706                else
 707                        low = mid;
 708        }
 709        return 0;
 710}
 711
 712/*
 713 * Free the dir_info structure when it isn't needed any more.
 714 */
 715static void e2fsck_free_dir_info(e2fsck_t ctx)
 716{
 717        ext2fs_free_mem(&ctx->dir_info);
 718        ctx->dir_info_size = 0;
 719        ctx->dir_info_count = 0;
 720}
 721
 722/*
 723 * Return the count of number of directories in the dir_info structure
 724 */
 725static int e2fsck_get_num_dirinfo(e2fsck_t ctx)
 726{
 727        return ctx->dir_info_count;
 728}
 729
 730/*
 731 * A simple interator function
 732 */
 733static struct dir_info *e2fsck_dir_info_iter(e2fsck_t ctx, int *control)
 734{
 735        if (*control >= ctx->dir_info_count)
 736                return 0;
 737
 738        return ctx->dir_info + (*control)++;
 739}
 740
 741/*
 742 * dirinfo.c --- maintains the directory information table for e2fsck.
 743 *
 744 */
 745
 746#ifdef ENABLE_HTREE
 747
 748/*
 749 * This subroutine is called during pass1 to create a directory info
 750 * entry.  During pass1, the passed-in parent is 0; it will get filled
 751 * in during pass2.
 752 */
 753static void e2fsck_add_dx_dir(e2fsck_t ctx, ext2_ino_t ino, int num_blocks)
 754{
 755        struct dx_dir_info *dir;
 756        int             i, j;
 757        errcode_t       retval;
 758        unsigned long   old_size;
 759
 760        if (!ctx->dx_dir_info) {
 761                ctx->dx_dir_info_count = 0;
 762                ctx->dx_dir_info_size = 100; /* Guess */
 763                ctx->dx_dir_info  = (struct dx_dir_info *)
 764                        e2fsck_allocate_memory(ctx, ctx->dx_dir_info_size
 765                                               * sizeof (struct dx_dir_info),
 766                                               "directory map");
 767        }
 768
 769        if (ctx->dx_dir_info_count >= ctx->dx_dir_info_size) {
 770                old_size = ctx->dx_dir_info_size * sizeof(struct dx_dir_info);
 771                ctx->dx_dir_info_size += 10;
 772                retval = ext2fs_resize_mem(old_size, ctx->dx_dir_info_size *
 773                                           sizeof(struct dx_dir_info),
 774                                           &ctx->dx_dir_info);
 775                if (retval) {
 776                        ctx->dx_dir_info_size -= 10;
 777                        return;
 778                }
 779        }
 780
 781        /*
 782         * Normally, add_dx_dir_info is called with each inode in
 783         * sequential order; but once in a while (like when pass 3
 784         * needs to recreate the root directory or lost+found
 785         * directory) it is called out of order.  In those cases, we
 786         * need to move the dx_dir_info entries down to make room, since
 787         * the dx_dir_info array needs to be sorted by inode number for
 788         * get_dx_dir_info()'s sake.
 789         */
 790        if (ctx->dx_dir_info_count &&
 791            ctx->dx_dir_info[ctx->dx_dir_info_count-1].ino >= ino) {
 792                for (i = ctx->dx_dir_info_count-1; i > 0; i--)
 793                        if (ctx->dx_dir_info[i-1].ino < ino)
 794                                break;
 795                dir = &ctx->dx_dir_info[i];
 796                if (dir->ino != ino)
 797                        for (j = ctx->dx_dir_info_count++; j > i; j--)
 798                                ctx->dx_dir_info[j] = ctx->dx_dir_info[j-1];
 799        } else
 800                dir = &ctx->dx_dir_info[ctx->dx_dir_info_count++];
 801
 802        dir->ino = ino;
 803        dir->numblocks = num_blocks;
 804        dir->hashversion = 0;
 805        dir->dx_block = e2fsck_allocate_memory(ctx, num_blocks
 806                                       * sizeof (struct dx_dirblock_info),
 807                                       "dx_block info array");
 808
 809}
 810
 811/*
 812 * get_dx_dir_info() --- given an inode number, try to find the directory
 813 * information entry for it.
 814 */
 815static struct dx_dir_info *e2fsck_get_dx_dir_info(e2fsck_t ctx, ext2_ino_t ino)
 816{
 817        int     low, high, mid;
 818
 819        low = 0;
 820        high = ctx->dx_dir_info_count-1;
 821        if (!ctx->dx_dir_info)
 822                return 0;
 823        if (ino == ctx->dx_dir_info[low].ino)
 824                return &ctx->dx_dir_info[low];
 825        if  (ino == ctx->dx_dir_info[high].ino)
 826                return &ctx->dx_dir_info[high];
 827
 828        while (low < high) {
 829                mid = (low+high)/2;
 830                if (mid == low || mid == high)
 831                        break;
 832                if (ino == ctx->dx_dir_info[mid].ino)
 833                        return &ctx->dx_dir_info[mid];
 834                if (ino < ctx->dx_dir_info[mid].ino)
 835                        high = mid;
 836                else
 837                        low = mid;
 838        }
 839        return 0;
 840}
 841
 842/*
 843 * Free the dx_dir_info structure when it isn't needed any more.
 844 */
 845static void e2fsck_free_dx_dir_info(e2fsck_t ctx)
 846{
 847        int     i;
 848        struct dx_dir_info *dir;
 849
 850        if (ctx->dx_dir_info) {
 851                dir = ctx->dx_dir_info;
 852                for (i=0; i < ctx->dx_dir_info_count; i++) {
 853                        ext2fs_free_mem(&dir->dx_block);
 854                }
 855                ext2fs_free_mem(&ctx->dx_dir_info);
 856        }
 857        ctx->dx_dir_info_size = 0;
 858        ctx->dx_dir_info_count = 0;
 859}
 860
 861/*
 862 * A simple interator function
 863 */
 864static struct dx_dir_info *e2fsck_dx_dir_info_iter(e2fsck_t ctx, int *control)
 865{
 866        if (*control >= ctx->dx_dir_info_count)
 867                return 0;
 868
 869        return ctx->dx_dir_info + (*control)++;
 870}
 871
 872#endif /* ENABLE_HTREE */
 873/*
 874 * e2fsck.c - a consistency checker for the new extended file system.
 875 *
 876 */
 877
 878/*
 879 * This function allocates an e2fsck context
 880 */
 881static errcode_t e2fsck_allocate_context(e2fsck_t *ret)
 882{
 883        e2fsck_t        context;
 884        errcode_t       retval;
 885
 886        retval = ext2fs_get_mem(sizeof(struct e2fsck_struct), &context);
 887        if (retval)
 888                return retval;
 889
 890        memset(context, 0, sizeof(struct e2fsck_struct));
 891
 892        context->process_inode_size = 256;
 893        context->ext_attr_ver = 2;
 894
 895        *ret = context;
 896        return 0;
 897}
 898
 899struct ea_refcount_el {
 900        blk_t   ea_blk;
 901        int     ea_count;
 902};
 903
 904struct ea_refcount {
 905        blk_t           count;
 906        blk_t           size;
 907        blk_t           cursor;
 908        struct ea_refcount_el   *list;
 909};
 910
 911static void ea_refcount_free(ext2_refcount_t refcount)
 912{
 913        if (!refcount)
 914                return;
 915
 916        ext2fs_free_mem(&refcount->list);
 917        ext2fs_free_mem(&refcount);
 918}
 919
 920/*
 921 * This function resets an e2fsck context; it is called when e2fsck
 922 * needs to be restarted.
 923 */
 924static errcode_t e2fsck_reset_context(e2fsck_t ctx)
 925{
 926        ctx->flags = 0;
 927        ctx->lost_and_found = 0;
 928        ctx->bad_lost_and_found = 0;
 929        ext2fs_free_inode_bitmap(ctx->inode_used_map);
 930        ctx->inode_used_map = 0;
 931        ext2fs_free_inode_bitmap(ctx->inode_dir_map);
 932        ctx->inode_dir_map = 0;
 933        ext2fs_free_inode_bitmap(ctx->inode_reg_map);
 934        ctx->inode_reg_map = 0;
 935        ext2fs_free_block_bitmap(ctx->block_found_map);
 936        ctx->block_found_map = 0;
 937        ext2fs_free_icount(ctx->inode_link_info);
 938        ctx->inode_link_info = 0;
 939        if (ctx->journal_io) {
 940                if (ctx->fs && ctx->fs->io != ctx->journal_io)
 941                        io_channel_close(ctx->journal_io);
 942                ctx->journal_io = 0;
 943        }
 944        if (ctx->fs) {
 945                ext2fs_free_dblist(ctx->fs->dblist);
 946                ctx->fs->dblist = 0;
 947        }
 948        e2fsck_free_dir_info(ctx);
 949#ifdef ENABLE_HTREE
 950        e2fsck_free_dx_dir_info(ctx);
 951#endif
 952        ea_refcount_free(ctx->refcount);
 953        ctx->refcount = 0;
 954        ea_refcount_free(ctx->refcount_extra);
 955        ctx->refcount_extra = 0;
 956        ext2fs_free_block_bitmap(ctx->block_dup_map);
 957        ctx->block_dup_map = 0;
 958        ext2fs_free_block_bitmap(ctx->block_ea_map);
 959        ctx->block_ea_map = 0;
 960        ext2fs_free_inode_bitmap(ctx->inode_bad_map);
 961        ctx->inode_bad_map = 0;
 962        ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
 963        ctx->inode_imagic_map = 0;
 964        ext2fs_u32_list_free(ctx->dirs_to_hash);
 965        ctx->dirs_to_hash = 0;
 966
 967        /*
 968         * Clear the array of invalid meta-data flags
 969         */
 970        ext2fs_free_mem(&ctx->invalid_inode_bitmap_flag);
 971        ext2fs_free_mem(&ctx->invalid_block_bitmap_flag);
 972        ext2fs_free_mem(&ctx->invalid_inode_table_flag);
 973
 974        /* Clear statistic counters */
 975        ctx->fs_directory_count = 0;
 976        ctx->fs_regular_count = 0;
 977        ctx->fs_blockdev_count = 0;
 978        ctx->fs_chardev_count = 0;
 979        ctx->fs_links_count = 0;
 980        ctx->fs_symlinks_count = 0;
 981        ctx->fs_fast_symlinks_count = 0;
 982        ctx->fs_fifo_count = 0;
 983        ctx->fs_total_count = 0;
 984        ctx->fs_sockets_count = 0;
 985        ctx->fs_ind_count = 0;
 986        ctx->fs_dind_count = 0;
 987        ctx->fs_tind_count = 0;
 988        ctx->fs_fragmented = 0;
 989        ctx->large_files = 0;
 990
 991        /* Reset the superblock to the user's requested value */
 992        ctx->superblock = ctx->use_superblock;
 993
 994        return 0;
 995}
 996
 997static void e2fsck_free_context(e2fsck_t ctx)
 998{
 999        if (!ctx)
1000                return;
1001
1002        e2fsck_reset_context(ctx);
1003        if (ctx->blkid)
1004                blkid_put_cache(ctx->blkid);
1005
1006        ext2fs_free_mem(&ctx);
1007}
1008
1009/*
1010 * ea_refcount.c
1011 */
1012
1013/*
1014 * The strategy we use for keeping track of EA refcounts is as
1015 * follows.  We keep a sorted array of first EA blocks and its
1016 * reference counts.  Once the refcount has dropped to zero, it is
1017 * removed from the array to save memory space.  Once the EA block is
1018 * checked, its bit is set in the block_ea_map bitmap.
1019 */
1020
1021
1022static errcode_t ea_refcount_create(int size, ext2_refcount_t *ret)
1023{
1024        ext2_refcount_t refcount;
1025        errcode_t       retval;
1026        size_t          bytes;
1027
1028        retval = ext2fs_get_mem(sizeof(struct ea_refcount), &refcount);
1029        if (retval)
1030                return retval;
1031        memset(refcount, 0, sizeof(struct ea_refcount));
1032
1033        if (!size)
1034                size = 500;
1035        refcount->size = size;
1036        bytes = (size_t) (size * sizeof(struct ea_refcount_el));
1037#ifdef DEBUG
1038        printf("Refcount allocated %d entries, %d bytes.\n",
1039               refcount->size, bytes);
1040#endif
1041        retval = ext2fs_get_mem(bytes, &refcount->list);
1042        if (retval)
1043                goto errout;
1044        memset(refcount->list, 0, bytes);
1045
1046        refcount->count = 0;
1047        refcount->cursor = 0;
1048
1049        *ret = refcount;
1050        return 0;
1051
1052errout:
1053        ea_refcount_free(refcount);
1054        return retval;
1055}
1056
1057/*
1058 * collapse_refcount() --- go through the refcount array, and get rid
1059 * of any count == zero entries
1060 */
1061static void refcount_collapse(ext2_refcount_t refcount)
1062{
1063        unsigned int    i, j;
1064        struct ea_refcount_el   *list;
1065
1066        list = refcount->list;
1067        for (i = 0, j = 0; i < refcount->count; i++) {
1068                if (list[i].ea_count) {
1069                        if (i != j)
1070                                list[j] = list[i];
1071                        j++;
1072                }
1073        }
1074#if defined(DEBUG) || defined(TEST_PROGRAM)
1075        printf("Refcount_collapse: size was %d, now %d\n",
1076               refcount->count, j);
1077#endif
1078        refcount->count = j;
1079}
1080
1081
1082/*
1083 * insert_refcount_el() --- Insert a new entry into the sorted list at a
1084 *      specified position.
1085 */
1086static struct ea_refcount_el *insert_refcount_el(ext2_refcount_t refcount,
1087                                                 blk_t blk, int pos)
1088{
1089        struct ea_refcount_el   *el;
1090        errcode_t               retval;
1091        blk_t                   new_size = 0;
1092        int                     num;
1093
1094        if (refcount->count >= refcount->size) {
1095                new_size = refcount->size + 100;
1096#ifdef DEBUG
1097                printf("Reallocating refcount %d entries...\n", new_size);
1098#endif
1099                retval = ext2fs_resize_mem((size_t) refcount->size *
1100                                           sizeof(struct ea_refcount_el),
1101                                           (size_t) new_size *
1102                                           sizeof(struct ea_refcount_el),
1103                                           &refcount->list);
1104                if (retval)
1105                        return 0;
1106                refcount->size = new_size;
1107        }
1108        num = (int) refcount->count - pos;
1109        if (num < 0)
1110                return 0;       /* should never happen */
1111        if (num) {
1112                memmove(&refcount->list[pos+1], &refcount->list[pos],
1113                        sizeof(struct ea_refcount_el) * num);
1114        }
1115        refcount->count++;
1116        el = &refcount->list[pos];
1117        el->ea_count = 0;
1118        el->ea_blk = blk;
1119        return el;
1120}
1121
1122
1123/*
1124 * get_refcount_el() --- given an block number, try to find refcount
1125 *      information in the sorted list.  If the create flag is set,
1126 *      and we can't find an entry, create one in the sorted list.
1127 */
1128static struct ea_refcount_el *get_refcount_el(ext2_refcount_t refcount,
1129                                              blk_t blk, int create)
1130{
1131        float   range;
1132        int     low, high, mid;
1133        blk_t   lowval, highval;
1134
1135        if (!refcount || !refcount->list)
1136                return 0;
1137retry:
1138        low = 0;
1139        high = (int) refcount->count-1;
1140        if (create && ((refcount->count == 0) ||
1141                       (blk > refcount->list[high].ea_blk))) {
1142                if (refcount->count >= refcount->size)
1143                        refcount_collapse(refcount);
1144
1145                return insert_refcount_el(refcount, blk,
1146                                          (unsigned) refcount->count);
1147        }
1148        if (refcount->count == 0)
1149                return 0;
1150
1151        if (refcount->cursor >= refcount->count)
1152                refcount->cursor = 0;
1153        if (blk == refcount->list[refcount->cursor].ea_blk)
1154                return &refcount->list[refcount->cursor++];
1155#ifdef DEBUG
1156        printf("Non-cursor get_refcount_el: %u\n", blk);
1157#endif
1158        while (low <= high) {
1159                if (low == high)
1160                        mid = low;
1161                else {
1162                        /* Interpolate for efficiency */
1163                        lowval = refcount->list[low].ea_blk;
1164                        highval = refcount->list[high].ea_blk;
1165
1166                        if (blk < lowval)
1167                                range = 0;
1168                        else if (blk > highval)
1169                                range = 1;
1170                        else
1171                                range = ((float) (blk - lowval)) /
1172                                        (highval - lowval);
1173                        mid = low + ((int) (range * (high-low)));
1174                }
1175
1176                if (blk == refcount->list[mid].ea_blk) {
1177                        refcount->cursor = mid+1;
1178                        return &refcount->list[mid];
1179                }
1180                if (blk < refcount->list[mid].ea_blk)
1181                        high = mid-1;
1182                else
1183                        low = mid+1;
1184        }
1185        /*
1186         * If we need to create a new entry, it should be right at
1187         * low (where high will be left at low-1).
1188         */
1189        if (create) {
1190                if (refcount->count >= refcount->size) {
1191                        refcount_collapse(refcount);
1192                        if (refcount->count < refcount->size)
1193                                goto retry;
1194                }
1195                return insert_refcount_el(refcount, blk, low);
1196        }
1197        return 0;
1198}
1199
1200static errcode_t
1201ea_refcount_increment(ext2_refcount_t refcount, blk_t blk, int *ret)
1202{
1203        struct ea_refcount_el   *el;
1204
1205        el = get_refcount_el(refcount, blk, 1);
1206        if (!el)
1207                return EXT2_ET_NO_MEMORY;
1208        el->ea_count++;
1209
1210        if (ret)
1211                *ret = el->ea_count;
1212        return 0;
1213}
1214
1215static errcode_t
1216ea_refcount_decrement(ext2_refcount_t refcount, blk_t blk, int *ret)
1217{
1218        struct ea_refcount_el   *el;
1219
1220        el = get_refcount_el(refcount, blk, 0);
1221        if (!el || el->ea_count == 0)
1222                return EXT2_ET_INVALID_ARGUMENT;
1223
1224        el->ea_count--;
1225
1226        if (ret)
1227                *ret = el->ea_count;
1228        return 0;
1229}
1230
1231static errcode_t
1232ea_refcount_store(ext2_refcount_t refcount, blk_t blk, int count)
1233{
1234        struct ea_refcount_el   *el;
1235
1236        /*
1237         * Get the refcount element
1238         */
1239        el = get_refcount_el(refcount, blk, count ? 1 : 0);
1240        if (!el)
1241                return count ? EXT2_ET_NO_MEMORY : 0;
1242        el->ea_count = count;
1243        return 0;
1244}
1245
1246static inline void ea_refcount_intr_begin(ext2_refcount_t refcount)
1247{
1248        refcount->cursor = 0;
1249}
1250
1251
1252static blk_t ea_refcount_intr_next(ext2_refcount_t refcount, int *ret)
1253{
1254        struct ea_refcount_el   *list;
1255
1256        while (1) {
1257                if (refcount->cursor >= refcount->count)
1258                        return 0;
1259                list = refcount->list;
1260                if (list[refcount->cursor].ea_count) {
1261                        if (ret)
1262                                *ret = list[refcount->cursor].ea_count;
1263                        return list[refcount->cursor++].ea_blk;
1264                }
1265                refcount->cursor++;
1266        }
1267}
1268
1269
1270/*
1271 * ehandler.c --- handle bad block errors which come up during the
1272 *      course of an e2fsck session.
1273 */
1274
1275
1276static const char *operation;
1277
1278static errcode_t
1279e2fsck_handle_read_error(io_channel channel, unsigned long block, int count,
1280                         void *data, size_t size FSCK_ATTR((unused)),
1281                         int actual FSCK_ATTR((unused)), errcode_t error)
1282{
1283        int     i;
1284        char    *p;
1285        ext2_filsys fs = (ext2_filsys) channel->app_data;
1286        e2fsck_t ctx;
1287
1288        ctx = (e2fsck_t) fs->priv_data;
1289
1290        /*
1291         * If more than one block was read, try reading each block
1292         * separately.  We could use the actual bytes read to figure
1293         * out where to start, but we don't bother.
1294         */
1295        if (count > 1) {
1296                p = (char *) data;
1297                for (i=0; i < count; i++, p += channel->block_size, block++) {
1298                        error = io_channel_read_blk(channel, block,
1299                                                    1, p);
1300                        if (error)
1301                                return error;
1302                }
1303                return 0;
1304        }
1305        if (operation)
1306                printf(_("Error reading block %lu (%s) while %s.  "), block,
1307                       error_message(error), operation);
1308        else
1309                printf(_("Error reading block %lu (%s).  "), block,
1310                       error_message(error));
1311        preenhalt(ctx);
1312        if (ask(ctx, _("Ignore error"), 1)) {
1313                if (ask(ctx, _("Force rewrite"), 1))
1314                        io_channel_write_blk(channel, block, 1, data);
1315                return 0;
1316        }
1317
1318        return error;
1319}
1320
1321static errcode_t
1322e2fsck_handle_write_error(io_channel channel, unsigned long block, int count,
1323                        const void *data, size_t size FSCK_ATTR((unused)),
1324                        int actual FSCK_ATTR((unused)), errcode_t error)
1325{
1326        int             i;
1327        const char      *p;
1328        ext2_filsys fs = (ext2_filsys) channel->app_data;
1329        e2fsck_t ctx;
1330
1331        ctx = (e2fsck_t) fs->priv_data;
1332
1333        /*
1334         * If more than one block was written, try writing each block
1335         * separately.  We could use the actual bytes read to figure
1336         * out where to start, but we don't bother.
1337         */
1338        if (count > 1) {
1339                p = (const char *) data;
1340                for (i=0; i < count; i++, p += channel->block_size, block++) {
1341                        error = io_channel_write_blk(channel, block,
1342                                                     1, p);
1343                        if (error)
1344                                return error;
1345                }
1346                return 0;
1347        }
1348
1349        if (operation)
1350                printf(_("Error writing block %lu (%s) while %s.  "), block,
1351                       error_message(error), operation);
1352        else
1353                printf(_("Error writing block %lu (%s).  "), block,
1354                       error_message(error));
1355        preenhalt(ctx);
1356        if (ask(ctx, _("Ignore error"), 1))
1357                return 0;
1358
1359        return error;
1360}
1361
1362static const char *ehandler_operation(const char *op)
1363{
1364        const char *ret = operation;
1365
1366        operation = op;
1367        return ret;
1368}
1369
1370static void ehandler_init(io_channel channel)
1371{
1372        channel->read_error = e2fsck_handle_read_error;
1373        channel->write_error = e2fsck_handle_write_error;
1374}
1375
1376/*
1377 * journal.c --- code for handling the "ext3" journal
1378 *
1379 * Copyright (C) 2000 Andreas Dilger
1380 * Copyright (C) 2000 Theodore Ts'o
1381 *
1382 * Parts of the code are based on fs/jfs/journal.c by Stephen C. Tweedie
1383 * Copyright (C) 1999 Red Hat Software
1384 *
1385 * This file may be redistributed under the terms of the
1386 * GNU General Public License version 2 or at your discretion
1387 * any later version.
1388 */
1389
1390/*
1391 * Define USE_INODE_IO to use the inode_io.c / fileio.c codepaths.
1392 * This creates a larger static binary, and a smaller binary using
1393 * shared libraries.  It's also probably slightly less CPU-efficient,
1394 * which is why it's not on by default.  But, it's a good way of
1395 * testing the functions in inode_io.c and fileio.c.
1396 */
1397#undef USE_INODE_IO
1398
1399/* Kernel compatibility functions for handling the journal.  These allow us
1400 * to use the recovery.c file virtually unchanged from the kernel, so we
1401 * don't have to do much to keep kernel and user recovery in sync.
1402 */
1403static int journal_bmap(journal_t *journal, blk_t block, unsigned long *phys)
1404{
1405#ifdef USE_INODE_IO
1406        *phys = block;
1407        return 0;
1408#else
1409        struct inode    *inode = journal->j_inode;
1410        errcode_t       retval;
1411        blk_t           pblk;
1412
1413        if (!inode) {
1414                *phys = block;
1415                return 0;
1416        }
1417
1418        retval= ext2fs_bmap(inode->i_ctx->fs, inode->i_ino,
1419                            &inode->i_ext2, NULL, 0, block, &pblk);
1420        *phys = pblk;
1421        return retval;
1422#endif
1423}
1424
1425static struct buffer_head *getblk(kdev_t kdev, blk_t blocknr, int blocksize)
1426{
1427        struct buffer_head *bh;
1428
1429        bh = e2fsck_allocate_memory(kdev->k_ctx, sizeof(*bh), "block buffer");
1430        if (!bh)
1431                return NULL;
1432
1433        bh->b_ctx = kdev->k_ctx;
1434        if (kdev->k_dev == K_DEV_FS)
1435                bh->b_io = kdev->k_ctx->fs->io;
1436        else
1437                bh->b_io = kdev->k_ctx->journal_io;
1438        bh->b_size = blocksize;
1439        bh->b_blocknr = blocknr;
1440
1441        return bh;
1442}
1443
1444static void sync_blockdev(kdev_t kdev)
1445{
1446        io_channel      io;
1447
1448        if (kdev->k_dev == K_DEV_FS)
1449                io = kdev->k_ctx->fs->io;
1450        else
1451                io = kdev->k_ctx->journal_io;
1452
1453        io_channel_flush(io);
1454}
1455
1456static void ll_rw_block(int rw, int nr, struct buffer_head *bhp[])
1457{
1458        int retval;
1459        struct buffer_head *bh;
1460
1461        for (; nr > 0; --nr) {
1462                bh = *bhp++;
1463                if (rw == READ && !bh->b_uptodate) {
1464                        retval = io_channel_read_blk(bh->b_io,
1465                                                     bh->b_blocknr,
1466                                                     1, bh->b_data);
1467                        if (retval) {
1468                                bb_error_msg("while reading block %lu",
1469                                        (unsigned long) bh->b_blocknr);
1470                                bh->b_err = retval;
1471                                continue;
1472                        }
1473                        bh->b_uptodate = 1;
1474                } else if (rw == WRITE && bh->b_dirty) {
1475                        retval = io_channel_write_blk(bh->b_io,
1476                                                      bh->b_blocknr,
1477                                                      1, bh->b_data);
1478                        if (retval) {
1479                                bb_error_msg("while writing block %lu",
1480                                        (unsigned long) bh->b_blocknr);
1481                                bh->b_err = retval;
1482                                continue;
1483                        }
1484                        bh->b_dirty = 0;
1485                        bh->b_uptodate = 1;
1486                }
1487        }
1488}
1489
1490static void mark_buffer_dirty(struct buffer_head *bh)
1491{
1492        bh->b_dirty = 1;
1493}
1494
1495static inline void mark_buffer_clean(struct buffer_head * bh)
1496{
1497        bh->b_dirty = 0;
1498}
1499
1500static void brelse(struct buffer_head *bh)
1501{
1502        if (bh->b_dirty)
1503                ll_rw_block(WRITE, 1, &bh);
1504        ext2fs_free_mem(&bh);
1505}
1506
1507static int buffer_uptodate(struct buffer_head *bh)
1508{
1509        return bh->b_uptodate;
1510}
1511
1512static inline void mark_buffer_uptodate(struct buffer_head *bh, int val)
1513{
1514        bh->b_uptodate = val;
1515}
1516
1517static void wait_on_buffer(struct buffer_head *bh)
1518{
1519        if (!bh->b_uptodate)
1520                ll_rw_block(READ, 1, &bh);
1521}
1522
1523
1524static void e2fsck_clear_recover(e2fsck_t ctx, int error)
1525{
1526        ctx->fs->super->s_feature_incompat &= ~EXT3_FEATURE_INCOMPAT_RECOVER;
1527
1528        /* if we had an error doing journal recovery, we need a full fsck */
1529        if (error)
1530                ctx->fs->super->s_state &= ~EXT2_VALID_FS;
1531        ext2fs_mark_super_dirty(ctx->fs);
1532}
1533
1534static errcode_t e2fsck_get_journal(e2fsck_t ctx, journal_t **ret_journal)
1535{
1536        struct ext2_super_block *sb = ctx->fs->super;
1537        struct ext2_super_block jsuper;
1538        struct problem_context  pctx;
1539        struct buffer_head      *bh;
1540        struct inode            *j_inode = NULL;
1541        struct kdev_s           *dev_fs = NULL, *dev_journal;
1542        const char              *journal_name = 0;
1543        journal_t               *journal = NULL;
1544        errcode_t               retval = 0;
1545        io_manager              io_ptr = 0;
1546        unsigned long           start = 0;
1547        blk_t                   blk;
1548        int                     ext_journal = 0;
1549        int                     tried_backup_jnl = 0;
1550        int                     i;
1551
1552        clear_problem_context(&pctx);
1553
1554        journal = e2fsck_allocate_memory(ctx, sizeof(journal_t), "journal");
1555        if (!journal) {
1556                return EXT2_ET_NO_MEMORY;
1557        }
1558
1559        dev_fs = e2fsck_allocate_memory(ctx, 2*sizeof(struct kdev_s), "kdev");
1560        if (!dev_fs) {
1561                retval = EXT2_ET_NO_MEMORY;
1562                goto errout;
1563        }
1564        dev_journal = dev_fs+1;
1565
1566        dev_fs->k_ctx = dev_journal->k_ctx = ctx;
1567        dev_fs->k_dev = K_DEV_FS;
1568        dev_journal->k_dev = K_DEV_JOURNAL;
1569
1570        journal->j_dev = dev_journal;
1571        journal->j_fs_dev = dev_fs;
1572        journal->j_inode = NULL;
1573        journal->j_blocksize = ctx->fs->blocksize;
1574
1575        if (uuid_is_null(sb->s_journal_uuid)) {
1576                if (!sb->s_journal_inum)
1577                        return EXT2_ET_BAD_INODE_NUM;
1578                j_inode = e2fsck_allocate_memory(ctx, sizeof(*j_inode),
1579                                                 "journal inode");
1580                if (!j_inode) {
1581                        retval = EXT2_ET_NO_MEMORY;
1582                        goto errout;
1583                }
1584
1585                j_inode->i_ctx = ctx;
1586                j_inode->i_ino = sb->s_journal_inum;
1587
1588                if ((retval = ext2fs_read_inode(ctx->fs,
1589                                                sb->s_journal_inum,
1590                                                &j_inode->i_ext2))) {
1591                try_backup_journal:
1592                        if (sb->s_jnl_backup_type != EXT3_JNL_BACKUP_BLOCKS ||
1593                            tried_backup_jnl)
1594                                goto errout;
1595                        memset(&j_inode->i_ext2, 0, sizeof(struct ext2_inode));
1596                        memcpy(&j_inode->i_ext2.i_block[0], sb->s_jnl_blocks,
1597                               EXT2_N_BLOCKS*4);
1598                        j_inode->i_ext2.i_size = sb->s_jnl_blocks[16];
1599                        j_inode->i_ext2.i_links_count = 1;
1600                        j_inode->i_ext2.i_mode = LINUX_S_IFREG | 0600;
1601                        tried_backup_jnl++;
1602                }
1603                if (!j_inode->i_ext2.i_links_count ||
1604                    !LINUX_S_ISREG(j_inode->i_ext2.i_mode)) {
1605                        retval = EXT2_ET_NO_JOURNAL;
1606                        goto try_backup_journal;
1607                }
1608                if (j_inode->i_ext2.i_size / journal->j_blocksize <
1609                    JFS_MIN_JOURNAL_BLOCKS) {
1610                        retval = EXT2_ET_JOURNAL_TOO_SMALL;
1611                        goto try_backup_journal;
1612                }
1613                for (i=0; i < EXT2_N_BLOCKS; i++) {
1614                        blk = j_inode->i_ext2.i_block[i];
1615                        if (!blk) {
1616                                if (i < EXT2_NDIR_BLOCKS) {
1617                                        retval = EXT2_ET_JOURNAL_TOO_SMALL;
1618                                        goto try_backup_journal;
1619                                }
1620                                continue;
1621                        }
1622                        if (blk < sb->s_first_data_block ||
1623                            blk >= sb->s_blocks_count) {
1624                                retval = EXT2_ET_BAD_BLOCK_NUM;
1625                                goto try_backup_journal;
1626                        }
1627                }
1628                journal->j_maxlen = j_inode->i_ext2.i_size / journal->j_blocksize;
1629
1630#ifdef USE_INODE_IO
1631                retval = ext2fs_inode_io_intern2(ctx->fs, sb->s_journal_inum,
1632                                                 &j_inode->i_ext2,
1633                                                 &journal_name);
1634                if (retval)
1635                        goto errout;
1636
1637                io_ptr = inode_io_manager;
1638#else
1639                journal->j_inode = j_inode;
1640                ctx->journal_io = ctx->fs->io;
1641                if ((retval = journal_bmap(journal, 0, &start)) != 0)
1642                        goto errout;
1643#endif
1644        } else {
1645                ext_journal = 1;
1646                if (!ctx->journal_name) {
1647                        char uuid[37];
1648
1649                        uuid_unparse(sb->s_journal_uuid, uuid);
1650                        ctx->journal_name = blkid_get_devname(ctx->blkid,
1651                                                              "UUID", uuid);
1652                        if (!ctx->journal_name)
1653                                ctx->journal_name = blkid_devno_to_devname(sb->s_journal_dev);
1654                }
1655                journal_name = ctx->journal_name;
1656
1657                if (!journal_name) {
1658                        fix_problem(ctx, PR_0_CANT_FIND_JOURNAL, &pctx);
1659                        return EXT2_ET_LOAD_EXT_JOURNAL;
1660                }
1661
1662                io_ptr = unix_io_manager;
1663        }
1664
1665#ifndef USE_INODE_IO
1666        if (ext_journal)
1667#endif
1668                retval = io_ptr->open(journal_name, IO_FLAG_RW,
1669                                      &ctx->journal_io);
1670        if (retval)
1671                goto errout;
1672
1673        io_channel_set_blksize(ctx->journal_io, ctx->fs->blocksize);
1674
1675        if (ext_journal) {
1676                if (ctx->fs->blocksize == 1024)
1677                        start = 1;
1678                bh = getblk(dev_journal, start, ctx->fs->blocksize);
1679                if (!bh) {
1680                        retval = EXT2_ET_NO_MEMORY;
1681                        goto errout;
1682                }
1683                ll_rw_block(READ, 1, &bh);
1684                if ((retval = bh->b_err) != 0)
1685                        goto errout;
1686                memcpy(&jsuper, start ? bh->b_data :  bh->b_data + 1024,
1687                       sizeof(jsuper));
1688                brelse(bh);
1689#if BB_BIG_ENDIAN
1690                if (jsuper.s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
1691                        ext2fs_swap_super(&jsuper);
1692#endif
1693                if (jsuper.s_magic != EXT2_SUPER_MAGIC ||
1694                    !(jsuper.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV)) {
1695                        fix_problem(ctx, PR_0_EXT_JOURNAL_BAD_SUPER, &pctx);
1696                        retval = EXT2_ET_LOAD_EXT_JOURNAL;
1697                        goto errout;
1698                }
1699                /* Make sure the journal UUID is correct */
1700                if (memcmp(jsuper.s_uuid, ctx->fs->super->s_journal_uuid,
1701                           sizeof(jsuper.s_uuid))) {
1702                        fix_problem(ctx, PR_0_JOURNAL_BAD_UUID, &pctx);
1703                        retval = EXT2_ET_LOAD_EXT_JOURNAL;
1704                        goto errout;
1705                }
1706
1707                journal->j_maxlen = jsuper.s_blocks_count;
1708                start++;
1709        }
1710
1711        if (!(bh = getblk(dev_journal, start, journal->j_blocksize))) {
1712                retval = EXT2_ET_NO_MEMORY;
1713                goto errout;
1714        }
1715
1716        journal->j_sb_buffer = bh;
1717        journal->j_superblock = (journal_superblock_t *)bh->b_data;
1718
1719#ifdef USE_INODE_IO
1720        ext2fs_free_mem(&j_inode);
1721#endif
1722
1723        *ret_journal = journal;
1724        return 0;
1725
1726errout:
1727        ext2fs_free_mem(&dev_fs);
1728        ext2fs_free_mem(&j_inode);
1729        ext2fs_free_mem(&journal);
1730        return retval;
1731
1732}
1733
1734static errcode_t e2fsck_journal_fix_bad_inode(e2fsck_t ctx,
1735                                              struct problem_context *pctx)
1736{
1737        struct ext2_super_block *sb = ctx->fs->super;
1738        int recover = ctx->fs->super->s_feature_incompat &
1739                EXT3_FEATURE_INCOMPAT_RECOVER;
1740        int has_journal = ctx->fs->super->s_feature_compat &
1741                EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1742
1743        if (has_journal || sb->s_journal_inum) {
1744                /* The journal inode is bogus, remove and force full fsck */
1745                pctx->ino = sb->s_journal_inum;
1746                if (fix_problem(ctx, PR_0_JOURNAL_BAD_INODE, pctx)) {
1747                        if (has_journal && sb->s_journal_inum)
1748                                printf("*** ext3 journal has been deleted - "
1749                                       "filesystem is now ext2 only ***\n\n");
1750                        sb->s_feature_compat &= ~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1751                        sb->s_journal_inum = 0;
1752                        ctx->flags |= E2F_FLAG_JOURNAL_INODE; /* FIXME: todo */
1753                        e2fsck_clear_recover(ctx, 1);
1754                        return 0;
1755                }
1756                return EXT2_ET_BAD_INODE_NUM;
1757        } else if (recover) {
1758                if (fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, pctx)) {
1759                        e2fsck_clear_recover(ctx, 1);
1760                        return 0;
1761                }
1762                return EXT2_ET_UNSUPP_FEATURE;
1763        }
1764        return 0;
1765}
1766
1767#define V1_SB_SIZE      0x0024
1768static void clear_v2_journal_fields(journal_t *journal)
1769{
1770        e2fsck_t ctx = journal->j_dev->k_ctx;
1771        struct problem_context pctx;
1772
1773        clear_problem_context(&pctx);
1774
1775        if (!fix_problem(ctx, PR_0_CLEAR_V2_JOURNAL, &pctx))
1776                return;
1777
1778        memset(((char *) journal->j_superblock) + V1_SB_SIZE, 0,
1779               ctx->fs->blocksize-V1_SB_SIZE);
1780        mark_buffer_dirty(journal->j_sb_buffer);
1781}
1782
1783
1784static errcode_t e2fsck_journal_load(journal_t *journal)
1785{
1786        e2fsck_t ctx = journal->j_dev->k_ctx;
1787        journal_superblock_t *jsb;
1788        struct buffer_head *jbh = journal->j_sb_buffer;
1789        struct problem_context pctx;
1790
1791        clear_problem_context(&pctx);
1792
1793        ll_rw_block(READ, 1, &jbh);
1794        if (jbh->b_err) {
1795                bb_error_msg(_("reading journal superblock"));
1796                return jbh->b_err;
1797        }
1798
1799        jsb = journal->j_superblock;
1800        /* If we don't even have JFS_MAGIC, we probably have a wrong inode */
1801        if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER))
1802                return e2fsck_journal_fix_bad_inode(ctx, &pctx);
1803
1804        switch (ntohl(jsb->s_header.h_blocktype)) {
1805        case JFS_SUPERBLOCK_V1:
1806                journal->j_format_version = 1;
1807                if (jsb->s_feature_compat ||
1808                    jsb->s_feature_incompat ||
1809                    jsb->s_feature_ro_compat ||
1810                    jsb->s_nr_users)
1811                        clear_v2_journal_fields(journal);
1812                break;
1813
1814        case JFS_SUPERBLOCK_V2:
1815                journal->j_format_version = 2;
1816                if (ntohl(jsb->s_nr_users) > 1 &&
1817                    uuid_is_null(ctx->fs->super->s_journal_uuid))
1818                        clear_v2_journal_fields(journal);
1819                if (ntohl(jsb->s_nr_users) > 1) {
1820                        fix_problem(ctx, PR_0_JOURNAL_UNSUPP_MULTIFS, &pctx);
1821                        return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1822                }
1823                break;
1824
1825        /*
1826         * These should never appear in a journal super block, so if
1827         * they do, the journal is badly corrupted.
1828         */
1829        case JFS_DESCRIPTOR_BLOCK:
1830        case JFS_COMMIT_BLOCK:
1831        case JFS_REVOKE_BLOCK:
1832                return EXT2_ET_CORRUPT_SUPERBLOCK;
1833
1834        /* If we don't understand the superblock major type, but there
1835         * is a magic number, then it is likely to be a new format we
1836         * just don't understand, so leave it alone. */
1837        default:
1838                return EXT2_ET_JOURNAL_UNSUPP_VERSION;
1839        }
1840
1841        if (JFS_HAS_INCOMPAT_FEATURE(journal, ~JFS_KNOWN_INCOMPAT_FEATURES))
1842                return EXT2_ET_UNSUPP_FEATURE;
1843
1844        if (JFS_HAS_RO_COMPAT_FEATURE(journal, ~JFS_KNOWN_ROCOMPAT_FEATURES))
1845                return EXT2_ET_RO_UNSUPP_FEATURE;
1846
1847        /* We have now checked whether we know enough about the journal
1848         * format to be able to proceed safely, so any other checks that
1849         * fail we should attempt to recover from. */
1850        if (jsb->s_blocksize != htonl(journal->j_blocksize)) {
1851                bb_error_msg(_("%s: no valid journal superblock found"),
1852                        ctx->device_name);
1853                return EXT2_ET_CORRUPT_SUPERBLOCK;
1854        }
1855
1856        if (ntohl(jsb->s_maxlen) < journal->j_maxlen)
1857                journal->j_maxlen = ntohl(jsb->s_maxlen);
1858        else if (ntohl(jsb->s_maxlen) > journal->j_maxlen) {
1859                bb_error_msg(_("%s: journal too short"),
1860                        ctx->device_name);
1861                return EXT2_ET_CORRUPT_SUPERBLOCK;
1862        }
1863
1864        journal->j_tail_sequence = ntohl(jsb->s_sequence);
1865        journal->j_transaction_sequence = journal->j_tail_sequence;
1866        journal->j_tail = ntohl(jsb->s_start);
1867        journal->j_first = ntohl(jsb->s_first);
1868        journal->j_last = ntohl(jsb->s_maxlen);
1869
1870        return 0;
1871}
1872
1873static void e2fsck_journal_reset_super(e2fsck_t ctx, journal_superblock_t *jsb,
1874                                       journal_t *journal)
1875{
1876        char *p;
1877        union {
1878                uuid_t uuid;
1879                __u32 val[4];
1880        } u;
1881        __u32 new_seq = 0;
1882        int i;
1883
1884        /* Leave a valid existing V1 superblock signature alone.
1885         * Anything unrecognizable we overwrite with a new V2
1886         * signature. */
1887
1888        if (jsb->s_header.h_magic != htonl(JFS_MAGIC_NUMBER) ||
1889            jsb->s_header.h_blocktype != htonl(JFS_SUPERBLOCK_V1)) {
1890                jsb->s_header.h_magic = htonl(JFS_MAGIC_NUMBER);
1891                jsb->s_header.h_blocktype = htonl(JFS_SUPERBLOCK_V2);
1892        }
1893
1894        /* Zero out everything else beyond the superblock header */
1895
1896        p = ((char *) jsb) + sizeof(journal_header_t);
1897        memset (p, 0, ctx->fs->blocksize-sizeof(journal_header_t));
1898
1899        jsb->s_blocksize = htonl(ctx->fs->blocksize);
1900        jsb->s_maxlen = htonl(journal->j_maxlen);
1901        jsb->s_first = htonl(1);
1902
1903        /* Initialize the journal sequence number so that there is "no"
1904         * chance we will find old "valid" transactions in the journal.
1905         * This avoids the need to zero the whole journal (slow to do,
1906         * and risky when we are just recovering the filesystem).
1907         */
1908        uuid_generate(u.uuid);
1909        for (i = 0; i < 4; i ++)
1910                new_seq ^= u.val[i];
1911        jsb->s_sequence = htonl(new_seq);
1912
1913        mark_buffer_dirty(journal->j_sb_buffer);
1914        ll_rw_block(WRITE, 1, &journal->j_sb_buffer);
1915}
1916
1917static errcode_t e2fsck_journal_fix_corrupt_super(e2fsck_t ctx,
1918                                                  journal_t *journal,
1919                                                  struct problem_context *pctx)
1920{
1921        struct ext2_super_block *sb = ctx->fs->super;
1922        int recover = ctx->fs->super->s_feature_incompat &
1923                EXT3_FEATURE_INCOMPAT_RECOVER;
1924
1925        if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) {
1926                if (fix_problem(ctx, PR_0_JOURNAL_BAD_SUPER, pctx)) {
1927                        e2fsck_journal_reset_super(ctx, journal->j_superblock,
1928                                                   journal);
1929                        journal->j_transaction_sequence = 1;
1930                        e2fsck_clear_recover(ctx, recover);
1931                        return 0;
1932                }
1933                return EXT2_ET_CORRUPT_SUPERBLOCK;
1934        } else if (e2fsck_journal_fix_bad_inode(ctx, pctx))
1935                return EXT2_ET_CORRUPT_SUPERBLOCK;
1936
1937        return 0;
1938}
1939
1940static void e2fsck_journal_release(e2fsck_t ctx, journal_t *journal,
1941                                   int reset, int drop)
1942{
1943        journal_superblock_t *jsb;
1944
1945        if (drop)
1946                mark_buffer_clean(journal->j_sb_buffer);
1947        else if (!(ctx->options & E2F_OPT_READONLY)) {
1948                jsb = journal->j_superblock;
1949                jsb->s_sequence = htonl(journal->j_transaction_sequence);
1950                if (reset)
1951                        jsb->s_start = 0; /* this marks the journal as empty */
1952                mark_buffer_dirty(journal->j_sb_buffer);
1953        }
1954        brelse(journal->j_sb_buffer);
1955
1956        if (ctx->journal_io) {
1957                if (ctx->fs && ctx->fs->io != ctx->journal_io)
1958                        io_channel_close(ctx->journal_io);
1959                ctx->journal_io = 0;
1960        }
1961
1962#ifndef USE_INODE_IO
1963        ext2fs_free_mem(&journal->j_inode);
1964#endif
1965        ext2fs_free_mem(&journal->j_fs_dev);
1966        ext2fs_free_mem(&journal);
1967}
1968
1969/*
1970 * This function makes sure that the superblock fields regarding the
1971 * journal are consistent.
1972 */
1973static int e2fsck_check_ext3_journal(e2fsck_t ctx)
1974{
1975        struct ext2_super_block *sb = ctx->fs->super;
1976        journal_t *journal;
1977        int recover = ctx->fs->super->s_feature_incompat &
1978                EXT3_FEATURE_INCOMPAT_RECOVER;
1979        struct problem_context pctx;
1980        problem_t problem;
1981        int reset = 0, force_fsck = 0;
1982        int retval;
1983
1984        /* If we don't have any journal features, don't do anything more */
1985        if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
1986            !recover && sb->s_journal_inum == 0 && sb->s_journal_dev == 0 &&
1987            uuid_is_null(sb->s_journal_uuid))
1988                return 0;
1989
1990        clear_problem_context(&pctx);
1991        pctx.num = sb->s_journal_inum;
1992
1993        retval = e2fsck_get_journal(ctx, &journal);
1994        if (retval) {
1995                if ((retval == EXT2_ET_BAD_INODE_NUM) ||
1996                    (retval == EXT2_ET_BAD_BLOCK_NUM) ||
1997                    (retval == EXT2_ET_JOURNAL_TOO_SMALL) ||
1998                    (retval == EXT2_ET_NO_JOURNAL))
1999                        return e2fsck_journal_fix_bad_inode(ctx, &pctx);
2000                return retval;
2001        }
2002
2003        retval = e2fsck_journal_load(journal);
2004        if (retval) {
2005                if ((retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
2006                    ((retval == EXT2_ET_UNSUPP_FEATURE) &&
2007                    (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_INCOMPAT,
2008                                  &pctx))) ||
2009                    ((retval == EXT2_ET_RO_UNSUPP_FEATURE) &&
2010                    (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_ROCOMPAT,
2011                                  &pctx))) ||
2012                    ((retval == EXT2_ET_JOURNAL_UNSUPP_VERSION) &&
2013                    (!fix_problem(ctx, PR_0_JOURNAL_UNSUPP_VERSION, &pctx))))
2014                        retval = e2fsck_journal_fix_corrupt_super(ctx, journal,
2015                                                                  &pctx);
2016                e2fsck_journal_release(ctx, journal, 0, 1);
2017                return retval;
2018        }
2019
2020        /*
2021         * We want to make the flags consistent here.  We will not leave with
2022         * needs_recovery set but has_journal clear.  We can't get in a loop
2023         * with -y, -n, or -p, only if a user isn't making up their mind.
2024         */
2025no_has_journal:
2026        if (!(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) {
2027                recover = sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER;
2028                pctx.str = "inode";
2029                if (fix_problem(ctx, PR_0_JOURNAL_HAS_JOURNAL, &pctx)) {
2030                        if (recover &&
2031                            !fix_problem(ctx, PR_0_JOURNAL_RECOVER_SET, &pctx))
2032                                goto no_has_journal;
2033                        /*
2034                         * Need a full fsck if we are releasing a
2035                         * journal stored on a reserved inode.
2036                         */
2037                        force_fsck = recover ||
2038                                (sb->s_journal_inum < EXT2_FIRST_INODE(sb));
2039                        /* Clear all of the journal fields */
2040                        sb->s_journal_inum = 0;
2041                        sb->s_journal_dev = 0;
2042                        memset(sb->s_journal_uuid, 0,
2043                               sizeof(sb->s_journal_uuid));
2044                        e2fsck_clear_recover(ctx, force_fsck);
2045                } else if (!(ctx->options & E2F_OPT_READONLY)) {
2046                        sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL;
2047                        ext2fs_mark_super_dirty(ctx->fs);
2048                }
2049        }
2050
2051        if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL &&
2052            !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) &&
2053            journal->j_superblock->s_start != 0) {
2054                /* Print status information */
2055                fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx);
2056                if (ctx->superblock)
2057                        problem = PR_0_JOURNAL_RUN_DEFAULT;
2058                else
2059                        problem = PR_0_JOURNAL_RUN;
2060                if (fix_problem(ctx, problem, &pctx)) {
2061                        ctx->options |= E2F_OPT_FORCE;
2062                        sb->s_feature_incompat |=
2063                                EXT3_FEATURE_INCOMPAT_RECOVER;
2064                        ext2fs_mark_super_dirty(ctx->fs);
2065                } else if (fix_problem(ctx,
2066                                       PR_0_JOURNAL_RESET_JOURNAL, &pctx)) {
2067                        reset = 1;
2068                        sb->s_state &= ~EXT2_VALID_FS;
2069                        ext2fs_mark_super_dirty(ctx->fs);
2070                }
2071                /*
2072                 * If the user answers no to the above question, we
2073                 * ignore the fact that journal apparently has data;
2074                 * accidentally replaying over valid data would be far
2075                 * worse than skipping a questionable recovery.
2076                 *
2077                 * XXX should we abort with a fatal error here?  What
2078                 * will the ext3 kernel code do if a filesystem with
2079                 * !NEEDS_RECOVERY but with a non-zero
2080                 * journal->j_superblock->s_start is mounted?
2081                 */
2082        }
2083
2084        e2fsck_journal_release(ctx, journal, reset, 0);
2085        return retval;
2086}
2087
2088static errcode_t recover_ext3_journal(e2fsck_t ctx)
2089{
2090        journal_t *journal;
2091        int retval;
2092
2093        journal_init_revoke_caches();
2094        retval = e2fsck_get_journal(ctx, &journal);
2095        if (retval)
2096                return retval;
2097
2098        retval = e2fsck_journal_load(journal);
2099        if (retval)
2100                goto errout;
2101
2102        retval = journal_init_revoke(journal, 1024);
2103        if (retval)
2104                goto errout;
2105
2106        retval = -journal_recover(journal);
2107        if (retval)
2108                goto errout;
2109
2110        if (journal->j_superblock->s_errno) {
2111                ctx->fs->super->s_state |= EXT2_ERROR_FS;
2112                ext2fs_mark_super_dirty(ctx->fs);
2113                journal->j_superblock->s_errno = 0;
2114                mark_buffer_dirty(journal->j_sb_buffer);
2115        }
2116
2117errout:
2118        journal_destroy_revoke(journal);
2119        journal_destroy_revoke_caches();
2120        e2fsck_journal_release(ctx, journal, 1, 0);
2121        return retval;
2122}
2123
2124static int e2fsck_run_ext3_journal(e2fsck_t ctx)
2125{
2126        io_manager io_ptr = ctx->fs->io->manager;
2127        int blocksize = ctx->fs->blocksize;
2128        errcode_t       retval, recover_retval;
2129
2130        printf(_("%s: recovering journal\n"), ctx->device_name);
2131        if (ctx->options & E2F_OPT_READONLY) {
2132                printf(_("%s: won't do journal recovery while read-only\n"),
2133                       ctx->device_name);
2134                return EXT2_ET_FILE_RO;
2135        }
2136
2137        if (ctx->fs->flags & EXT2_FLAG_DIRTY)
2138                ext2fs_flush(ctx->fs);  /* Force out any modifications */
2139
2140        recover_retval = recover_ext3_journal(ctx);
2141
2142        /*
2143         * Reload the filesystem context to get up-to-date data from disk
2144         * because journal recovery will change the filesystem under us.
2145         */
2146        ext2fs_close(ctx->fs);
2147        retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW,
2148                             ctx->superblock, blocksize, io_ptr,
2149                             &ctx->fs);
2150
2151        if (retval) {
2152                bb_error_msg(_("while trying to re-open %s"),
2153                        ctx->device_name);
2154                bb_error_msg_and_die(0);
2155        }
2156        ctx->fs->priv_data = ctx;
2157
2158        /* Set the superblock flags */
2159        e2fsck_clear_recover(ctx, recover_retval);
2160        return recover_retval;
2161}
2162
2163/*
2164 * This function will move the journal inode from a visible file in
2165 * the filesystem directory hierarchy to the reserved inode if necessary.
2166 */
2167static const char *const journal_names[] = {
2168        ".journal", "journal", ".journal.dat", "journal.dat", 0 };
2169
2170static void e2fsck_move_ext3_journal(e2fsck_t ctx)
2171{
2172        struct ext2_super_block *sb = ctx->fs->super;
2173        struct problem_context  pctx;
2174        struct ext2_inode       inode;
2175        ext2_filsys             fs = ctx->fs;
2176        ext2_ino_t              ino;
2177        errcode_t               retval;
2178        const char *const *    cpp;
2179        int                     group, mount_flags;
2180
2181        clear_problem_context(&pctx);
2182
2183        /*
2184         * If the filesystem is opened read-only, or there is no
2185         * journal, then do nothing.
2186         */
2187        if ((ctx->options & E2F_OPT_READONLY) ||
2188            (sb->s_journal_inum == 0) ||
2189            !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL))
2190                return;
2191
2192        /*
2193         * Read in the journal inode
2194         */
2195        if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0)
2196                return;
2197
2198        /*
2199         * If it's necessary to backup the journal inode, do so.
2200         */
2201        if ((sb->s_jnl_backup_type == 0) ||
2202            ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) &&
2203             memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) {
2204                if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) {
2205                        memcpy(sb->s_jnl_blocks, inode.i_block,
2206                               EXT2_N_BLOCKS*4);
2207                        sb->s_jnl_blocks[16] = inode.i_size;
2208                        sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS;
2209                        ext2fs_mark_super_dirty(fs);
2210                        fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2211                }
2212        }
2213
2214        /*
2215         * If the journal is already the hidden inode, then do nothing
2216         */
2217        if (sb->s_journal_inum == EXT2_JOURNAL_INO)
2218                return;
2219
2220        /*
2221         * The journal inode had better have only one link and not be readable.
2222         */
2223        if (inode.i_links_count != 1)
2224                return;
2225
2226        /*
2227         * If the filesystem is mounted, or we can't tell whether
2228         * or not it's mounted, do nothing.
2229         */
2230        retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags);
2231        if (retval || (mount_flags & EXT2_MF_MOUNTED))
2232                return;
2233
2234        /*
2235         * If we can't find the name of the journal inode, then do
2236         * nothing.
2237         */
2238        for (cpp = journal_names; *cpp; cpp++) {
2239                retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp,
2240                                       strlen(*cpp), 0, &ino);
2241                if ((retval == 0) && (ino == sb->s_journal_inum))
2242                        break;
2243        }
2244        if (*cpp == 0)
2245                return;
2246
2247        /* We need the inode bitmap to be loaded */
2248        retval = ext2fs_read_bitmaps(fs);
2249        if (retval)
2250                return;
2251
2252        pctx.str = *cpp;
2253        if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx))
2254                return;
2255
2256        /*
2257         * OK, we've done all the checks, let's actually move the
2258         * journal inode.  Errors at this point mean we need to force
2259         * an ext2 filesystem check.
2260         */
2261        if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0)
2262                goto err_out;
2263        if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0)
2264                goto err_out;
2265        sb->s_journal_inum = EXT2_JOURNAL_INO;
2266        ext2fs_mark_super_dirty(fs);
2267        fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
2268        inode.i_links_count = 0;
2269        inode.i_dtime = time(NULL);
2270        if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0)
2271                goto err_out;
2272
2273        group = ext2fs_group_of_ino(fs, ino);
2274        ext2fs_unmark_inode_bitmap(fs->inode_map, ino);
2275        ext2fs_mark_ib_dirty(fs);
2276        fs->group_desc[group].bg_free_inodes_count++;
2277        fs->super->s_free_inodes_count++;
2278        return;
2279
2280err_out:
2281        pctx.errcode = retval;
2282        fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx);
2283        fs->super->s_state &= ~EXT2_VALID_FS;
2284        ext2fs_mark_super_dirty(fs);
2285}
2286
2287/*
2288 * message.c --- print e2fsck messages (with compression)
2289 *
2290 * print_e2fsck_message() prints a message to the user, using
2291 * compression techniques and expansions of abbreviations.
2292 *
2293 * The following % expansions are supported:
2294 *
2295 *      %b      <blk>                   block number
2296 *      %B      <blkcount>              integer
2297 *      %c      <blk2>                  block number
2298 *      %Di     <dirent>->ino           inode number
2299 *      %Dn     <dirent>->name          string
2300 *      %Dr     <dirent>->rec_len
2301 *      %Dl     <dirent>->name_len
2302 *      %Dt     <dirent>->filetype
2303 *      %d      <dir>                   inode number
2304 *      %g      <group>                 integer
2305 *      %i      <ino>                   inode number
2306 *      %Is     <inode> -> i_size
2307 *      %IS     <inode> -> i_extra_isize
2308 *      %Ib     <inode> -> i_blocks
2309 *      %Il     <inode> -> i_links_count
2310 *      %Im     <inode> -> i_mode
2311 *      %IM     <inode> -> i_mtime
2312 *      %IF     <inode> -> i_faddr
2313 *      %If     <inode> -> i_file_acl
2314 *      %Id     <inode> -> i_dir_acl
2315 *      %Iu     <inode> -> i_uid
2316 *      %Ig     <inode> -> i_gid
2317 *      %j      <ino2>                  inode number
2318 *      %m      <com_err error message>
2319 *      %N      <num>
2320 *      %p      ext2fs_get_pathname of directory <ino>
2321 *      %P      ext2fs_get_pathname of <dirent>->ino with <ino2> as
2322 *                      the containing directory.  (If dirent is NULL
2323 *                      then return the pathname of directory <ino2>)
2324 *      %q      ext2fs_get_pathname of directory <dir>
2325 *      %Q      ext2fs_get_pathname of directory <ino> with <dir> as
2326 *                      the containing directory.
2327 *      %s      <str>                   miscellaneous string
2328 *      %S      backup superblock
2329 *      %X      <num> hexadecimal format
2330 *
2331 * The following '@' expansions are supported:
2332 *
2333 *      @a      extended attribute
2334 *      @A      error allocating
2335 *      @b      block
2336 *      @B      bitmap
2337 *      @c      compress
2338 *      @C      conflicts with some other fs block
2339 *      @D      deleted
2340 *      @d      directory
2341 *      @e      entry
2342 *      @E      Entry '%Dn' in %p (%i)
2343 *      @f      filesystem
2344 *      @F      for @i %i (%Q) is
2345 *      @g      group
2346 *      @h      HTREE directory inode
2347 *      @i      inode
2348 *      @I      illegal
2349 *      @j      journal
2350 *      @l      lost+found
2351 *      @L      is a link
2352 *      @m      multiply-claimed
2353 *      @n      invalid
2354 *      @o      orphaned
2355 *      @p      problem in
2356 *      @r      root inode
2357 *      @s      should be
2358 *      @S      superblock
2359 *      @u      unattached
2360 *      @v      device
2361 *      @z      zero-length
2362 */
2363
2364
2365/*
2366 * This structure defines the abbreviations used by the text strings
2367 * below.  The first character in the string is the index letter.  An
2368 * abbreviation of the form '@<i>' is expanded by looking up the index
2369 * letter <i> in the table below.
2370 */
2371static const char *const abbrevs[] = {
2372        N_("aextended attribute"),
2373        N_("Aerror allocating"),
2374        N_("bblock"),
2375        N_("Bbitmap"),
2376        N_("ccompress"),
2377        N_("Cconflicts with some other fs @b"),
2378        N_("iinode"),
2379        N_("Iillegal"),
2380        N_("jjournal"),
2381        N_("Ddeleted"),
2382        N_("ddirectory"),
2383        N_("eentry"),
2384        N_("E@e '%Dn' in %p (%i)"),
2385        N_("ffilesystem"),
2386        N_("Ffor @i %i (%Q) is"),
2387        N_("ggroup"),
2388        N_("hHTREE @d @i"),
2389        N_("llost+found"),
2390        N_("Lis a link"),
2391        N_("mmultiply-claimed"),
2392        N_("ninvalid"),
2393        N_("oorphaned"),
2394        N_("pproblem in"),
2395        N_("rroot @i"),
2396        N_("sshould be"),
2397        N_("Ssuper@b"),
2398        N_("uunattached"),
2399        N_("vdevice"),
2400        N_("zzero-length"),
2401        "@@",
2402        0
2403        };
2404
2405/*
2406 * Give more user friendly names to the "special" inodes.
2407 */
2408#define num_special_inodes      11
2409static const char *const special_inode_name[] =
2410{
2411        N_("<The NULL inode>"),                 /* 0 */
2412        N_("<The bad blocks inode>"),           /* 1 */
2413        "/",                                    /* 2 */
2414        N_("<The ACL index inode>"),            /* 3 */
2415        N_("<The ACL data inode>"),             /* 4 */
2416        N_("<The boot loader inode>"),          /* 5 */
2417        N_("<The undelete directory inode>"),   /* 6 */
2418        N_("<The group descriptor inode>"),     /* 7 */
2419        N_("<The journal inode>"),              /* 8 */
2420        N_("<Reserved inode 9>"),               /* 9 */
2421        N_("<Reserved inode 10>"),              /* 10 */
2422};
2423
2424/*
2425 * This function does "safe" printing.  It will convert non-printable
2426 * ASCII characters using '^' and M- notation.
2427 */
2428static void safe_print(const char *cp, int len)
2429{
2430        unsigned char   ch;
2431
2432        if (len < 0)
2433                len = strlen(cp);
2434
2435        while (len--) {
2436                ch = *cp++;
2437                if (ch > 128) {
2438                        fputs("M-", stdout);
2439                        ch -= 128;
2440                }
2441                if ((ch < 32) || (ch == 0x7f)) {
2442                        bb_putchar('^');
2443                        ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */
2444                }
2445                bb_putchar(ch);
2446        }
2447}
2448
2449
2450/*
2451 * This function prints a pathname, using the ext2fs_get_pathname
2452 * function
2453 */
2454static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino)
2455{
2456        errcode_t       retval;
2457        char            *path;
2458
2459        if (!dir && (ino < num_special_inodes)) {
2460                fputs(_(special_inode_name[ino]), stdout);
2461                return;
2462        }
2463
2464        retval = ext2fs_get_pathname(fs, dir, ino, &path);
2465        if (retval)
2466                fputs("???", stdout);
2467        else {
2468                safe_print(path, -1);
2469                ext2fs_free_mem(&path);
2470        }
2471}
2472
2473static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2474                          struct problem_context *pctx, int first);
2475/*
2476 * This function handles the '@' expansion.  We allow recursive
2477 * expansion; an @ expression can contain further '@' and '%'
2478 * expressions.
2479 */
2480static void expand_at_expression(e2fsck_t ctx, char ch,
2481                                          struct problem_context *pctx,
2482                                          int *first)
2483{
2484        const char *const *cpp;
2485        const char *str;
2486
2487        /* Search for the abbreviation */
2488        for (cpp = abbrevs; *cpp; cpp++) {
2489                if (ch == *cpp[0])
2490                        break;
2491        }
2492        if (*cpp) {
2493                str = _(*cpp) + 1;
2494                if (*first && islower(*str)) {
2495                        *first = 0;
2496                        bb_putchar(toupper(*str++));
2497                }
2498                print_e2fsck_message(ctx, str, pctx, *first);
2499        } else
2500                printf("@%c", ch);
2501}
2502
2503/*
2504 * This function expands '%IX' expressions
2505 */
2506static void expand_inode_expression(char ch,
2507                                             struct problem_context *ctx)
2508{
2509        struct ext2_inode       *inode;
2510        struct ext2_inode_large *large_inode;
2511        char *                  time_str;
2512        time_t                  t;
2513        int                     do_gmt = -1;
2514
2515        if (!ctx || !ctx->inode)
2516                goto no_inode;
2517
2518        inode = ctx->inode;
2519        large_inode = (struct ext2_inode_large *) inode;
2520
2521        switch (ch) {
2522        case 's':
2523                if (LINUX_S_ISDIR(inode->i_mode))
2524                        printf("%u", inode->i_size);
2525                else {
2526                        printf("%"PRIu64, (inode->i_size |
2527                                        ((uint64_t) inode->i_size_high << 32)));
2528                }
2529                break;
2530        case 'S':
2531                printf("%u", large_inode->i_extra_isize);
2532                break;
2533        case 'b':
2534                printf("%u", inode->i_blocks);
2535                break;
2536        case 'l':
2537                printf("%d", inode->i_links_count);
2538                break;
2539        case 'm':
2540                printf("0%o", inode->i_mode);
2541                break;
2542        case 'M':
2543                /* The diet libc doesn't respect the TZ environemnt variable */
2544                if (do_gmt == -1) {
2545                        time_str = getenv("TZ");
2546                        if (!time_str)
2547                                time_str = "";
2548                        do_gmt = !strcmp(time_str, "GMT");
2549                }
2550                t = inode->i_mtime;
2551                time_str = asctime(do_gmt ? gmtime(&t) : localtime(&t));
2552                printf("%.24s", time_str);
2553                break;
2554        case 'F':
2555                printf("%u", inode->i_faddr);
2556                break;
2557        case 'f':
2558                printf("%u", inode->i_file_acl);
2559                break;
2560        case 'd':
2561                printf("%u", (LINUX_S_ISDIR(inode->i_mode) ?
2562                              inode->i_dir_acl : 0));
2563                break;
2564        case 'u':
2565                printf("%d", (inode->i_uid |
2566                              (inode->osd2.linux2.l_i_uid_high << 16)));
2567                break;
2568        case 'g':
2569                printf("%d", (inode->i_gid |
2570                              (inode->osd2.linux2.l_i_gid_high << 16)));
2571                break;
2572        default:
2573        no_inode:
2574                printf("%%I%c", ch);
2575                break;
2576        }
2577}
2578
2579/*
2580 * This function expands '%dX' expressions
2581 */
2582static void expand_dirent_expression(char ch,
2583                                              struct problem_context *ctx)
2584{
2585        struct ext2_dir_entry   *dirent;
2586        int     len;
2587
2588        if (!ctx || !ctx->dirent)
2589                goto no_dirent;
2590
2591        dirent = ctx->dirent;
2592
2593        switch (ch) {
2594        case 'i':
2595                printf("%u", dirent->inode);
2596                break;
2597        case 'n':
2598                len = dirent->name_len & 0xFF;
2599                if (len > EXT2_NAME_LEN)
2600                        len = EXT2_NAME_LEN;
2601                if (len > dirent->rec_len)
2602                        len = dirent->rec_len;
2603                safe_print(dirent->name, len);
2604                break;
2605        case 'r':
2606                printf("%u", dirent->rec_len);
2607                break;
2608        case 'l':
2609                printf("%u", dirent->name_len & 0xFF);
2610                break;
2611        case 't':
2612                printf("%u", dirent->name_len >> 8);
2613                break;
2614        default:
2615        no_dirent:
2616                printf("%%D%c", ch);
2617                break;
2618        }
2619}
2620
2621static void expand_percent_expression(ext2_filsys fs, char ch,
2622                                               struct problem_context *ctx)
2623{
2624        if (!ctx)
2625                goto no_context;
2626
2627        switch (ch) {
2628        case '%':
2629                bb_putchar('%');
2630                break;
2631        case 'b':
2632                printf("%u", ctx->blk);
2633                break;
2634        case 'B':
2635                printf("%"PRIi64, ctx->blkcount);
2636                break;
2637        case 'c':
2638                printf("%u", ctx->blk2);
2639                break;
2640        case 'd':
2641                printf("%u", ctx->dir);
2642                break;
2643        case 'g':
2644                printf("%d", ctx->group);
2645                break;
2646        case 'i':
2647                printf("%u", ctx->ino);
2648                break;
2649        case 'j':
2650                printf("%u", ctx->ino2);
2651                break;
2652        case 'm':
2653                fputs(error_message(ctx->errcode), stdout);
2654                break;
2655        case 'N':
2656                printf("%"PRIi64, ctx->num);
2657                break;
2658        case 'p':
2659                print_pathname(fs, ctx->ino, 0);
2660                break;
2661        case 'P':
2662                print_pathname(fs, ctx->ino2,
2663                               ctx->dirent ? ctx->dirent->inode : 0);
2664                break;
2665        case 'q':
2666                print_pathname(fs, ctx->dir, 0);
2667                break;
2668        case 'Q':
2669                print_pathname(fs, ctx->dir, ctx->ino);
2670                break;
2671        case 'S':
2672                printf("%d", get_backup_sb(NULL, fs, NULL, NULL));
2673                break;
2674        case 's':
2675                fputs((ctx->str ? ctx->str : "NULL"), stdout);
2676                break;
2677        case 'X':
2678                printf("0x%"PRIi64, ctx->num);
2679                break;
2680        default:
2681        no_context:
2682                printf("%%%c", ch);
2683                break;
2684        }
2685}
2686
2687
2688static void print_e2fsck_message(e2fsck_t ctx, const char *msg,
2689                          struct problem_context *pctx, int first)
2690{
2691        ext2_filsys fs = ctx->fs;
2692        const char *    cp;
2693        int             i;
2694
2695        e2fsck_clear_progbar(ctx);
2696        for (cp = msg; *cp; cp++) {
2697                if (cp[0] == '@') {
2698                        cp++;
2699                        expand_at_expression(ctx, *cp, pctx, &first);
2700                } else if (cp[0] == '%' && cp[1] == 'I') {
2701                        cp += 2;
2702                        expand_inode_expression(*cp, pctx);
2703                } else if (cp[0] == '%' && cp[1] == 'D') {
2704                        cp += 2;
2705                        expand_dirent_expression(*cp, pctx);
2706                } else if ((cp[0] == '%')) {
2707                        cp++;
2708                        expand_percent_expression(fs, *cp, pctx);
2709                } else {
2710                        for (i=0; cp[i]; i++)
2711                                if ((cp[i] == '@') || cp[i] == '%')
2712                                        break;
2713                        printf("%.*s", i, cp);
2714                        cp += i-1;
2715                }
2716                first = 0;
2717        }
2718}
2719
2720
2721/*
2722 * region.c --- code which manages allocations within a region.
2723 */
2724
2725struct region_el {
2726        region_addr_t   start;
2727        region_addr_t   end;
2728        struct region_el *next;
2729};
2730
2731struct region_struct {
2732        region_addr_t   min;
2733        region_addr_t   max;
2734        struct region_el *allocated;
2735};
2736
2737static region_t region_create(region_addr_t min, region_addr_t max)
2738{
2739        region_t        region;
2740
2741        region = xzalloc(sizeof(struct region_struct));
2742        region->min = min;
2743        region->max = max;
2744        return region;
2745}
2746
2747static void region_free(region_t region)
2748{
2749        struct region_el        *r, *next;
2750
2751        for (r = region->allocated; r; r = next) {
2752                next = r->next;
2753                free(r);
2754        }
2755        memset(region, 0, sizeof(struct region_struct));
2756        free(region);
2757}
2758
2759static int region_allocate(region_t region, region_addr_t start, int n)
2760{
2761        struct region_el        *r, *new_region, *prev, *next;
2762        region_addr_t end;
2763
2764        end = start+n;
2765        if ((start < region->min) || (end > region->max))
2766                return -1;
2767        if (n == 0)
2768                return 1;
2769
2770        /*
2771         * Search through the linked list.  If we find that it
2772         * conflicts witih something that's already allocated, return
2773         * 1; if we can find an existing region which we can grow, do
2774         * so.  Otherwise, stop when we find the appropriate place
2775         * insert a new region element into the linked list.
2776         */
2777        for (r = region->allocated, prev=NULL; r; prev = r, r = r->next) {
2778                if (((start >= r->start) && (start < r->end)) ||
2779                    ((end > r->start) && (end <= r->end)) ||
2780                    ((start <= r->start) && (end >= r->end)))
2781                        return 1;
2782                if (end == r->start) {
2783                        r->start = start;
2784                        return 0;
2785                }
2786                if (start == r->end) {
2787                        if ((next = r->next)) {
2788                                if (end > next->start)
2789                                        return 1;
2790                                if (end == next->start) {
2791                                        r->end = next->end;
2792                                        r->next = next->next;
2793                                        free(next);
2794                                        return 0;
2795                                }
2796                        }
2797                        r->end = end;
2798                        return 0;
2799                }
2800                if (start < r->start)
2801                        break;
2802        }
2803        /*
2804         * Insert a new region element structure into the linked list
2805         */
2806        new_region = xmalloc(sizeof(struct region_el));
2807        new_region->start = start;
2808        new_region->end = start + n;
2809        new_region->next = r;
2810        if (prev)
2811                prev->next = new_region;
2812        else
2813                region->allocated = new_region;
2814        return 0;
2815}
2816
2817/*
2818 * pass1.c -- pass #1 of e2fsck: sequential scan of the inode table
2819 *
2820 * Pass 1 of e2fsck iterates over all the inodes in the filesystems,
2821 * and applies the following tests to each inode:
2822 *
2823 *      - The mode field of the inode must be legal.
2824 *      - The size and block count fields of the inode are correct.
2825 *      - A data block must not be used by another inode
2826 *
2827 * Pass 1 also gathers the collects the following information:
2828 *
2829 *      - A bitmap of which inodes are in use.          (inode_used_map)
2830 *      - A bitmap of which inodes are directories.     (inode_dir_map)
2831 *      - A bitmap of which inodes are regular files.   (inode_reg_map)
2832 *      - A bitmap of which inodes have bad fields.     (inode_bad_map)
2833 *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
2834 *      - A bitmap of which blocks are in use.          (block_found_map)
2835 *      - A bitmap of which blocks are in use by two inodes     (block_dup_map)
2836 *      - The data blocks of the directory inodes.      (dir_map)
2837 *
2838 * Pass 1 is designed to stash away enough information so that the
2839 * other passes should not need to read in the inode information
2840 * during the normal course of a filesystem check.  (Althogh if an
2841 * inconsistency is detected, other passes may need to read in an
2842 * inode to fix it.)
2843 *
2844 * Note that pass 1B will be invoked if there are any duplicate blocks
2845 * found.
2846 */
2847
2848
2849static int process_block(ext2_filsys fs, blk_t  *blocknr,
2850                         e2_blkcnt_t blockcnt, blk_t ref_blk,
2851                         int ref_offset, void *priv_data);
2852static int process_bad_block(ext2_filsys fs, blk_t *block_nr,
2853                             e2_blkcnt_t blockcnt, blk_t ref_blk,
2854                             int ref_offset, void *priv_data);
2855static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
2856                         char *block_buf);
2857static void mark_table_blocks(e2fsck_t ctx);
2858static void alloc_imagic_map(e2fsck_t ctx);
2859static void mark_inode_bad(e2fsck_t ctx, ino_t ino);
2860static void handle_fs_bad_blocks(e2fsck_t ctx);
2861static void process_inodes(e2fsck_t ctx, char *block_buf);
2862static int process_inode_cmp(const void *a, const void *b);
2863static errcode_t scan_callback(ext2_filsys fs,
2864                                  dgrp_t group, void * priv_data);
2865static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
2866                                    char *block_buf, int adjust_sign);
2867/* static char *describe_illegal_block(ext2_filsys fs, blk_t block); */
2868
2869static void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
2870                               struct ext2_inode * inode, int bufsize,
2871                               const char *proc);
2872
2873struct process_block_struct_1 {
2874        ext2_ino_t      ino;
2875        unsigned        is_dir:1, is_reg:1, clear:1, suppress:1,
2876                                fragmented:1, compressed:1, bbcheck:1;
2877        blk_t           num_blocks;
2878        blk_t           max_blocks;
2879        e2_blkcnt_t     last_block;
2880        int             num_illegal_blocks;
2881        blk_t           previous_block;
2882        struct ext2_inode *inode;
2883        struct problem_context *pctx;
2884        ext2fs_block_bitmap fs_meta_blocks;
2885        e2fsck_t        ctx;
2886};
2887
2888struct process_inode_block {
2889        ext2_ino_t ino;
2890        struct ext2_inode inode;
2891};
2892
2893struct scan_callback_struct {
2894        e2fsck_t        ctx;
2895        char            *block_buf;
2896};
2897
2898/*
2899 * For the inodes to process list.
2900 */
2901static struct process_inode_block *inodes_to_process;
2902static int process_inode_count;
2903
2904static __u64 ext2_max_sizes[EXT2_MAX_BLOCK_LOG_SIZE -
2905                            EXT2_MIN_BLOCK_LOG_SIZE + 1];
2906
2907/*
2908 * Free all memory allocated by pass1 in preparation for restarting
2909 * things.
2910 */
2911static void unwind_pass1(void)
2912{
2913        ext2fs_free_mem(&inodes_to_process);
2914}
2915
2916/*
2917 * Check to make sure a device inode is real.  Returns 1 if the device
2918 * checks out, 0 if not.
2919 *
2920 * Note: this routine is now also used to check FIFO's and Sockets,
2921 * since they have the same requirement; the i_block fields should be
2922 * zero.
2923 */
2924static int
2925e2fsck_pass1_check_device_inode(ext2_filsys fs, struct ext2_inode *inode)
2926{
2927        int     i;
2928
2929        /*
2930         * If i_blocks is non-zero, or the index flag is set, then
2931         * this is a bogus device/fifo/socket
2932         */
2933        if ((ext2fs_inode_data_blocks(fs, inode) != 0) ||
2934            (inode->i_flags & EXT2_INDEX_FL))
2935                return 0;
2936
2937        /*
2938         * We should be able to do the test below all the time, but
2939         * because the kernel doesn't forcibly clear the device
2940         * inode's additional i_block fields, there are some rare
2941         * occasions when a legitimate device inode will have non-zero
2942         * additional i_block fields.  So for now, we only complain
2943         * when the immutable flag is set, which should never happen
2944         * for devices.  (And that's when the problem is caused, since
2945         * you can't set or clear immutable flags for devices.)  Once
2946         * the kernel has been fixed we can change this...
2947         */
2948        if (inode->i_flags & (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)) {
2949                for (i=4; i < EXT2_N_BLOCKS; i++)
2950                        if (inode->i_block[i])
2951                                return 0;
2952        }
2953        return 1;
2954}
2955
2956/*
2957 * Check to make sure a symlink inode is real.  Returns 1 if the symlink
2958 * checks out, 0 if not.
2959 */
2960static int
2961e2fsck_pass1_check_symlink(ext2_filsys fs, struct ext2_inode *inode, char *buf)
2962{
2963        unsigned int len;
2964        int i;
2965        blk_t   blocks;
2966
2967        if ((inode->i_size_high || inode->i_size == 0) ||
2968            (inode->i_flags & EXT2_INDEX_FL))
2969                return 0;
2970
2971        blocks = ext2fs_inode_data_blocks(fs, inode);
2972        if (blocks) {
2973                if ((inode->i_size >= fs->blocksize) ||
2974                    (blocks != fs->blocksize >> 9) ||
2975                    (inode->i_block[0] < fs->super->s_first_data_block) ||
2976                    (inode->i_block[0] >= fs->super->s_blocks_count))
2977                        return 0;
2978
2979                for (i = 1; i < EXT2_N_BLOCKS; i++)
2980                        if (inode->i_block[i])
2981                                return 0;
2982
2983                if (io_channel_read_blk(fs->io, inode->i_block[0], 1, buf))
2984                        return 0;
2985
2986                len = strnlen(buf, fs->blocksize);
2987                if (len == fs->blocksize)
2988                        return 0;
2989        } else {
2990                if (inode->i_size >= sizeof(inode->i_block))
2991                        return 0;
2992
2993                len = strnlen((char *)inode->i_block, sizeof(inode->i_block));
2994                if (len == sizeof(inode->i_block))
2995                        return 0;
2996        }
2997        if (len != inode->i_size)
2998                return 0;
2999        return 1;
3000}
3001
3002/*
3003 * If the immutable (or append-only) flag is set on the inode, offer
3004 * to clear it.
3005 */
3006#define BAD_SPECIAL_FLAGS (EXT2_IMMUTABLE_FL | EXT2_APPEND_FL)
3007static void check_immutable(e2fsck_t ctx, struct problem_context *pctx)
3008{
3009        if (!(pctx->inode->i_flags & BAD_SPECIAL_FLAGS))
3010                return;
3011
3012        if (!fix_problem(ctx, PR_1_SET_IMMUTABLE, pctx))
3013                return;
3014
3015        pctx->inode->i_flags &= ~BAD_SPECIAL_FLAGS;
3016        e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3017}
3018
3019/*
3020 * If device, fifo or socket, check size is zero -- if not offer to
3021 * clear it
3022 */
3023static void check_size(e2fsck_t ctx, struct problem_context *pctx)
3024{
3025        struct ext2_inode *inode = pctx->inode;
3026
3027        if ((inode->i_size == 0) && (inode->i_size_high == 0))
3028                return;
3029
3030        if (!fix_problem(ctx, PR_1_SET_NONZSIZE, pctx))
3031                return;
3032
3033        inode->i_size = 0;
3034        inode->i_size_high = 0;
3035        e2fsck_write_inode(ctx, pctx->ino, pctx->inode, "pass1");
3036}
3037
3038static void check_ea_in_inode(e2fsck_t ctx, struct problem_context *pctx)
3039{
3040        struct ext2_super_block *sb = ctx->fs->super;
3041        struct ext2_inode_large *inode;
3042        struct ext2_ext_attr_entry *entry;
3043        char *start, *end;
3044        int storage_size, remain, offs;
3045        int problem = 0;
3046
3047        inode = (struct ext2_inode_large *) pctx->inode;
3048        storage_size = EXT2_INODE_SIZE(ctx->fs->super) - EXT2_GOOD_OLD_INODE_SIZE -
3049                inode->i_extra_isize;
3050        start = ((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3051                inode->i_extra_isize + sizeof(__u32);
3052        end = (char *) inode + EXT2_INODE_SIZE(ctx->fs->super);
3053        entry = (struct ext2_ext_attr_entry *) start;
3054
3055        /* scan all entry's headers first */
3056
3057        /* take finish entry 0UL into account */
3058        remain = storage_size - sizeof(__u32);
3059        offs = end - start;
3060
3061        while (!EXT2_EXT_IS_LAST_ENTRY(entry)) {
3062
3063                /* header eats this space */
3064                remain -= sizeof(struct ext2_ext_attr_entry);
3065
3066                /* is attribute name valid? */
3067                if (EXT2_EXT_ATTR_SIZE(entry->e_name_len) > remain) {
3068                        pctx->num = entry->e_name_len;
3069                        problem = PR_1_ATTR_NAME_LEN;
3070                        goto fix;
3071                }
3072
3073                /* attribute len eats this space */
3074                remain -= EXT2_EXT_ATTR_SIZE(entry->e_name_len);
3075
3076                /* check value size */
3077                if (entry->e_value_size == 0 || entry->e_value_size > remain) {
3078                        pctx->num = entry->e_value_size;
3079                        problem = PR_1_ATTR_VALUE_SIZE;
3080                        goto fix;
3081                }
3082
3083                /* check value placement */
3084                if (entry->e_value_offs +
3085                    EXT2_XATTR_SIZE(entry->e_value_size) != offs) {
3086                        printf("(entry->e_value_offs + entry->e_value_size: %d, offs: %d)\n", entry->e_value_offs + entry->e_value_size, offs);
3087                        pctx->num = entry->e_value_offs;
3088                        problem = PR_1_ATTR_VALUE_OFFSET;
3089                        goto fix;
3090                }
3091
3092                /* e_value_block must be 0 in inode's ea */
3093                if (entry->e_value_block != 0) {
3094                        pctx->num = entry->e_value_block;
3095                        problem = PR_1_ATTR_VALUE_BLOCK;
3096                        goto fix;
3097                }
3098
3099                /* e_hash must be 0 in inode's ea */
3100                if (entry->e_hash != 0) {
3101                        pctx->num = entry->e_hash;
3102                        problem = PR_1_ATTR_HASH;
3103                        goto fix;
3104                }
3105
3106                remain -= entry->e_value_size;
3107                offs -= EXT2_XATTR_SIZE(entry->e_value_size);
3108
3109                entry = EXT2_EXT_ATTR_NEXT(entry);
3110        }
3111fix:
3112        /*
3113         * it seems like a corruption. it's very unlikely we could repair
3114         * EA(s) in automatic fashion -bzzz
3115         */
3116        if (problem == 0 || !fix_problem(ctx, problem, pctx))
3117                return;
3118
3119        /* simple remove all possible EA(s) */
3120        *((__u32 *)start) = 0UL;
3121        e2fsck_write_inode_full(ctx, pctx->ino, (struct ext2_inode *)inode,
3122                                EXT2_INODE_SIZE(sb), "pass1");
3123}
3124
3125static void check_inode_extra_space(e2fsck_t ctx, struct problem_context *pctx)
3126{
3127        struct ext2_super_block *sb = ctx->fs->super;
3128        struct ext2_inode_large *inode;
3129        __u32 *eamagic;
3130        int min, max;
3131
3132        inode = (struct ext2_inode_large *) pctx->inode;
3133        if (EXT2_INODE_SIZE(sb) == EXT2_GOOD_OLD_INODE_SIZE) {
3134                /* this isn't large inode. so, nothing to check */
3135                return;
3136        }
3137
3138        /* i_extra_isize must cover i_extra_isize + i_pad1 at least */
3139        min = sizeof(inode->i_extra_isize) + sizeof(inode->i_pad1);
3140        max = EXT2_INODE_SIZE(sb) - EXT2_GOOD_OLD_INODE_SIZE;
3141        /*
3142         * For now we will allow i_extra_isize to be 0, but really
3143         * implementations should never allow i_extra_isize to be 0
3144         */
3145        if (inode->i_extra_isize &&
3146            (inode->i_extra_isize < min || inode->i_extra_isize > max)) {
3147                if (!fix_problem(ctx, PR_1_EXTRA_ISIZE, pctx))
3148                        return;
3149                inode->i_extra_isize = min;
3150                e2fsck_write_inode_full(ctx, pctx->ino, pctx->inode,
3151                                        EXT2_INODE_SIZE(sb), "pass1");
3152                return;
3153        }
3154
3155        eamagic = (__u32 *) (((char *) inode) + EXT2_GOOD_OLD_INODE_SIZE +
3156                        inode->i_extra_isize);
3157        if (*eamagic == EXT2_EXT_ATTR_MAGIC) {
3158                /* it seems inode has an extended attribute(s) in body */
3159                check_ea_in_inode(ctx, pctx);
3160        }
3161}
3162
3163static void e2fsck_pass1(e2fsck_t ctx)
3164{
3165        int     i;
3166        __u64   max_sizes;
3167        ext2_filsys fs = ctx->fs;
3168        ext2_ino_t      ino;
3169        struct ext2_inode *inode;
3170        ext2_inode_scan scan;
3171        char            *block_buf;
3172        unsigned char   frag, fsize;
3173        struct          problem_context pctx;
3174        struct          scan_callback_struct scan_struct;
3175        struct ext2_super_block *sb = ctx->fs->super;
3176        int             imagic_fs;
3177        int             busted_fs_time = 0;
3178        int             inode_size;
3179
3180        clear_problem_context(&pctx);
3181
3182        if (!(ctx->options & E2F_OPT_PREEN))
3183                fix_problem(ctx, PR_1_PASS_HEADER, &pctx);
3184
3185        if ((fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
3186            !(ctx->options & E2F_OPT_NO)) {
3187                if (ext2fs_u32_list_create(&ctx->dirs_to_hash, 50))
3188                        ctx->dirs_to_hash = 0;
3189        }
3190
3191        /* Pass 1 */
3192
3193#define EXT2_BPP(bits) (1ULL << ((bits) - 2))
3194
3195        for (i = EXT2_MIN_BLOCK_LOG_SIZE; i <= EXT2_MAX_BLOCK_LOG_SIZE; i++) {
3196                max_sizes = EXT2_NDIR_BLOCKS + EXT2_BPP(i);
3197                max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i);
3198                max_sizes = max_sizes + EXT2_BPP(i) * EXT2_BPP(i) * EXT2_BPP(i);
3199                max_sizes = (max_sizes * (1UL << i)) - 1;
3200                ext2_max_sizes[i - EXT2_MIN_BLOCK_LOG_SIZE] = max_sizes;
3201        }
3202#undef EXT2_BPP
3203
3204        imagic_fs = (sb->s_feature_compat & EXT2_FEATURE_COMPAT_IMAGIC_INODES);
3205
3206        /*
3207         * Allocate bitmaps structures
3208         */
3209        pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("in-use inode map"),
3210                                              &ctx->inode_used_map);
3211        if (pctx.errcode) {
3212                pctx.num = 1;
3213                fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3214                ctx->flags |= E2F_FLAG_ABORT;
3215                return;
3216        }
3217        pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3218                                _("directory inode map"), &ctx->inode_dir_map);
3219        if (pctx.errcode) {
3220                pctx.num = 2;
3221                fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3222                ctx->flags |= E2F_FLAG_ABORT;
3223                return;
3224        }
3225        pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
3226                        _("regular file inode map"), &ctx->inode_reg_map);
3227        if (pctx.errcode) {
3228                pctx.num = 6;
3229                fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3230                ctx->flags |= E2F_FLAG_ABORT;
3231                return;
3232        }
3233        pctx.errcode = ext2fs_allocate_block_bitmap(fs, _("in-use block map"),
3234                                              &ctx->block_found_map);
3235        if (pctx.errcode) {
3236                pctx.num = 1;
3237                fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3238                ctx->flags |= E2F_FLAG_ABORT;
3239                return;
3240        }
3241        pctx.errcode = ext2fs_create_icount2(fs, 0, 0, 0,
3242                                             &ctx->inode_link_info);
3243        if (pctx.errcode) {
3244                fix_problem(ctx, PR_1_ALLOCATE_ICOUNT, &pctx);
3245                ctx->flags |= E2F_FLAG_ABORT;
3246                return;
3247        }
3248        inode_size = EXT2_INODE_SIZE(fs->super);
3249        inode = (struct ext2_inode *)
3250                e2fsck_allocate_memory(ctx, inode_size, "scratch inode");
3251
3252        inodes_to_process = (struct process_inode_block *)
3253                e2fsck_allocate_memory(ctx,
3254                                       (ctx->process_inode_size *
3255                                        sizeof(struct process_inode_block)),
3256                                       "array of inodes to process");
3257        process_inode_count = 0;
3258
3259        pctx.errcode = ext2fs_init_dblist(fs, 0);
3260        if (pctx.errcode) {
3261                fix_problem(ctx, PR_1_ALLOCATE_DBCOUNT, &pctx);
3262                ctx->flags |= E2F_FLAG_ABORT;
3263                return;
3264        }
3265
3266        /*
3267         * If the last orphan field is set, clear it, since the pass1
3268         * processing will automatically find and clear the orphans.
3269         * In the future, we may want to try using the last_orphan
3270         * linked list ourselves, but for now, we clear it so that the
3271         * ext3 mount code won't get confused.
3272         */
3273        if (!(ctx->options & E2F_OPT_READONLY)) {
3274                if (fs->super->s_last_orphan) {
3275                        fs->super->s_last_orphan = 0;
3276                        ext2fs_mark_super_dirty(fs);
3277                }
3278        }
3279
3280        mark_table_blocks(ctx);
3281        block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 3,
3282                                                    "block interate buffer");
3283        e2fsck_use_inode_shortcuts(ctx, 1);
3284        ehandler_operation(_("doing inode scan"));
3285        pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
3286                                              &scan);
3287        if (pctx.errcode) {
3288                fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3289                ctx->flags |= E2F_FLAG_ABORT;
3290                return;
3291        }
3292        ext2fs_inode_scan_flags(scan, EXT2_SF_SKIP_MISSING_ITABLE, 0);
3293        ctx->stashed_inode = inode;
3294        scan_struct.ctx = ctx;
3295        scan_struct.block_buf = block_buf;
3296        ext2fs_set_inode_callback(scan, scan_callback, &scan_struct);
3297        if (ctx->progress)
3298                if ((ctx->progress)(ctx, 1, 0, ctx->fs->group_desc_count))
3299                        return;
3300        if ((fs->super->s_wtime < fs->super->s_inodes_count) ||
3301            (fs->super->s_mtime < fs->super->s_inodes_count))
3302                busted_fs_time = 1;
3303
3304        while (1) {
3305                pctx.errcode = ext2fs_get_next_inode_full(scan, &ino,
3306                                                          inode, inode_size);
3307                if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3308                        return;
3309                if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE) {
3310                        continue;
3311                }
3312                if (pctx.errcode) {
3313                        fix_problem(ctx, PR_1_ISCAN_ERROR, &pctx);
3314                        ctx->flags |= E2F_FLAG_ABORT;
3315                        return;
3316                }
3317                if (!ino)
3318                        break;
3319                pctx.ino = ino;
3320                pctx.inode = inode;
3321                ctx->stashed_ino = ino;
3322                if (inode->i_links_count) {
3323                        pctx.errcode = ext2fs_icount_store(ctx->inode_link_info,
3324                                           ino, inode->i_links_count);
3325                        if (pctx.errcode) {
3326                                pctx.num = inode->i_links_count;
3327                                fix_problem(ctx, PR_1_ICOUNT_STORE, &pctx);
3328                                ctx->flags |= E2F_FLAG_ABORT;
3329                                return;
3330                        }
3331                }
3332                if (ino == EXT2_BAD_INO) {
3333                        struct process_block_struct_1 pb;
3334
3335                        pctx.errcode = ext2fs_copy_bitmap(ctx->block_found_map,
3336                                                          &pb.fs_meta_blocks);
3337                        if (pctx.errcode) {
3338                                pctx.num = 4;
3339                                fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, &pctx);
3340                                ctx->flags |= E2F_FLAG_ABORT;
3341                                return;
3342                        }
3343                        pb.ino = EXT2_BAD_INO;
3344                        pb.num_blocks = pb.last_block = 0;
3345                        pb.num_illegal_blocks = 0;
3346                        pb.suppress = 0; pb.clear = 0; pb.is_dir = 0;
3347                        pb.is_reg = 0; pb.fragmented = 0; pb.bbcheck = 0;
3348                        pb.inode = inode;
3349                        pb.pctx = &pctx;
3350                        pb.ctx = ctx;
3351                        pctx.errcode = ext2fs_block_iterate2(fs, ino, 0,
3352                                     block_buf, process_bad_block, &pb);
3353                        ext2fs_free_block_bitmap(pb.fs_meta_blocks);
3354                        if (pctx.errcode) {
3355                                fix_problem(ctx, PR_1_BLOCK_ITERATE, &pctx);
3356                                ctx->flags |= E2F_FLAG_ABORT;
3357                                return;
3358                        }
3359                        if (pb.bbcheck)
3360                                if (!fix_problem(ctx, PR_1_BBINODE_BAD_METABLOCK_PROMPT, &pctx)) {
3361                                ctx->flags |= E2F_FLAG_ABORT;
3362                                return;
3363                        }
3364                        ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3365                        clear_problem_context(&pctx);
3366                        continue;
3367                } else if (ino == EXT2_ROOT_INO) {
3368                        /*
3369                         * Make sure the root inode is a directory; if
3370                         * not, offer to clear it.  It will be
3371                         * regnerated in pass #3.
3372                         */
3373                        if (!LINUX_S_ISDIR(inode->i_mode)) {
3374                                if (fix_problem(ctx, PR_1_ROOT_NO_DIR, &pctx)) {
3375                                        inode->i_dtime = time(NULL);
3376                                        inode->i_links_count = 0;
3377                                        ext2fs_icount_store(ctx->inode_link_info,
3378                                                            ino, 0);
3379                                        e2fsck_write_inode(ctx, ino, inode,
3380                                                           "pass1");
3381                                }
3382
3383                        }
3384                        /*
3385                         * If dtime is set, offer to clear it.  mke2fs
3386                         * version 0.2b created filesystems with the
3387                         * dtime field set for the root and lost+found
3388                         * directories.  We won't worry about
3389                         * /lost+found, since that can be regenerated
3390                         * easily.  But we will fix the root directory
3391                         * as a special case.
3392                         */
3393                        if (inode->i_dtime && inode->i_links_count) {
3394                                if (fix_problem(ctx, PR_1_ROOT_DTIME, &pctx)) {
3395                                        inode->i_dtime = 0;
3396                                        e2fsck_write_inode(ctx, ino, inode,
3397                                                           "pass1");
3398                                }
3399                        }
3400                } else if (ino == EXT2_JOURNAL_INO) {
3401                        ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3402                        if (fs->super->s_journal_inum == EXT2_JOURNAL_INO) {
3403                                if (!LINUX_S_ISREG(inode->i_mode) &&
3404                                    fix_problem(ctx, PR_1_JOURNAL_BAD_MODE,
3405                                                &pctx)) {
3406                                        inode->i_mode = LINUX_S_IFREG;
3407                                        e2fsck_write_inode(ctx, ino, inode,
3408                                                           "pass1");
3409                                }
3410                                check_blocks(ctx, &pctx, block_buf);
3411                                continue;
3412                        }
3413                        if ((inode->i_links_count || inode->i_blocks ||
3414                             inode->i_blocks || inode->i_block[0]) &&
3415                            fix_problem(ctx, PR_1_JOURNAL_INODE_NOT_CLEAR,
3416                                        &pctx)) {
3417                                memset(inode, 0, inode_size);
3418                                ext2fs_icount_store(ctx->inode_link_info,
3419                                                    ino, 0);
3420                                e2fsck_write_inode_full(ctx, ino, inode,
3421                                                        inode_size, "pass1");
3422                        }
3423                } else if (ino < EXT2_FIRST_INODE(fs->super)) {
3424                        int     problem = 0;
3425
3426                        ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3427                        if (ino == EXT2_BOOT_LOADER_INO) {
3428                                if (LINUX_S_ISDIR(inode->i_mode))
3429                                        problem = PR_1_RESERVED_BAD_MODE;
3430                        } else if (ino == EXT2_RESIZE_INO) {
3431                                if (inode->i_mode &&
3432                                    !LINUX_S_ISREG(inode->i_mode))
3433                                        problem = PR_1_RESERVED_BAD_MODE;
3434                        } else {
3435                                if (inode->i_mode != 0)
3436                                        problem = PR_1_RESERVED_BAD_MODE;
3437                        }
3438                        if (problem) {
3439                                if (fix_problem(ctx, problem, &pctx)) {
3440                                        inode->i_mode = 0;
3441                                        e2fsck_write_inode(ctx, ino, inode,
3442                                                           "pass1");
3443                                }
3444                        }
3445                        check_blocks(ctx, &pctx, block_buf);
3446                        continue;
3447                }
3448                /*
3449                 * Check for inodes who might have been part of the
3450                 * orphaned list linked list.  They should have gotten
3451                 * dealt with by now, unless the list had somehow been
3452                 * corrupted.
3453                 *
3454                 * FIXME: In the future, inodes which are still in use
3455                 * (and which are therefore) pending truncation should
3456                 * be handled specially.  Right now we just clear the
3457                 * dtime field, and the normal e2fsck handling of
3458                 * inodes where i_size and the inode blocks are
3459                 * inconsistent is to fix i_size, instead of releasing
3460                 * the extra blocks.  This won't catch the inodes that
3461                 * was at the end of the orphan list, but it's better
3462                 * than nothing.  The right answer is that there
3463                 * shouldn't be any bugs in the orphan list handling.  :-)
3464                 */
3465                if (inode->i_dtime && !busted_fs_time &&
3466                    inode->i_dtime < ctx->fs->super->s_inodes_count) {
3467                        if (fix_problem(ctx, PR_1_LOW_DTIME, &pctx)) {
3468                                inode->i_dtime = inode->i_links_count ?
3469                                        0 : time(NULL);
3470                                e2fsck_write_inode(ctx, ino, inode,
3471                                                   "pass1");
3472                        }
3473                }
3474
3475                /*
3476                 * This code assumes that deleted inodes have
3477                 * i_links_count set to 0.
3478                 */
3479                if (!inode->i_links_count) {
3480                        if (!inode->i_dtime && inode->i_mode) {
3481                                if (fix_problem(ctx,
3482                                            PR_1_ZERO_DTIME, &pctx)) {
3483                                        inode->i_dtime = time(NULL);
3484                                        e2fsck_write_inode(ctx, ino, inode,
3485                                                           "pass1");
3486                                }
3487                        }
3488                        continue;
3489                }
3490                /*
3491                 * n.b.  0.3c ext2fs code didn't clear i_links_count for
3492                 * deleted files.  Oops.
3493                 *
3494                 * Since all new ext2 implementations get this right,
3495                 * we now assume that the case of non-zero
3496                 * i_links_count and non-zero dtime means that we
3497                 * should keep the file, not delete it.
3498                 *
3499                 */
3500                if (inode->i_dtime) {
3501                        if (fix_problem(ctx, PR_1_SET_DTIME, &pctx)) {
3502                                inode->i_dtime = 0;
3503                                e2fsck_write_inode(ctx, ino, inode, "pass1");
3504                        }
3505                }
3506
3507                ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
3508                switch (fs->super->s_creator_os) {
3509                    case EXT2_OS_LINUX:
3510                        frag = inode->osd2.linux2.l_i_frag;
3511                        fsize = inode->osd2.linux2.l_i_fsize;
3512                        break;
3513                    case EXT2_OS_HURD:
3514                        frag = inode->osd2.hurd2.h_i_frag;
3515                        fsize = inode->osd2.hurd2.h_i_fsize;
3516                        break;
3517                    case EXT2_OS_MASIX:
3518                        frag = inode->osd2.masix2.m_i_frag;
3519                        fsize = inode->osd2.masix2.m_i_fsize;
3520                        break;
3521                    default:
3522                        frag = fsize = 0;
3523                }
3524
3525                if (inode->i_faddr || frag || fsize ||
3526                    (LINUX_S_ISDIR(inode->i_mode) && inode->i_dir_acl))
3527                        mark_inode_bad(ctx, ino);
3528                if (inode->i_flags & EXT2_IMAGIC_FL) {
3529                        if (imagic_fs) {
3530                                if (!ctx->inode_imagic_map)
3531                                        alloc_imagic_map(ctx);
3532                                ext2fs_mark_inode_bitmap(ctx->inode_imagic_map,
3533                                                         ino);
3534                        } else {
3535                                if (fix_problem(ctx, PR_1_SET_IMAGIC, &pctx)) {
3536                                        inode->i_flags &= ~EXT2_IMAGIC_FL;
3537                                        e2fsck_write_inode(ctx, ino,
3538                                                           inode, "pass1");
3539                                }
3540                        }
3541                }
3542
3543                check_inode_extra_space(ctx, &pctx);
3544
3545                if (LINUX_S_ISDIR(inode->i_mode)) {
3546                        ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
3547                        e2fsck_add_dir_info(ctx, ino, 0);
3548                        ctx->fs_directory_count++;
3549                } else if (LINUX_S_ISREG (inode->i_mode)) {
3550                        ext2fs_mark_inode_bitmap(ctx->inode_reg_map, ino);
3551                        ctx->fs_regular_count++;
3552                } else if (LINUX_S_ISCHR (inode->i_mode) &&
3553                           e2fsck_pass1_check_device_inode(fs, inode)) {
3554                        check_immutable(ctx, &pctx);
3555                        check_size(ctx, &pctx);
3556                        ctx->fs_chardev_count++;
3557                } else if (LINUX_S_ISBLK (inode->i_mode) &&
3558                           e2fsck_pass1_check_device_inode(fs, inode)) {
3559                        check_immutable(ctx, &pctx);
3560                        check_size(ctx, &pctx);
3561                        ctx->fs_blockdev_count++;
3562                } else if (LINUX_S_ISLNK (inode->i_mode) &&
3563                           e2fsck_pass1_check_symlink(fs, inode, block_buf)) {
3564                        check_immutable(ctx, &pctx);
3565                        ctx->fs_symlinks_count++;
3566                        if (ext2fs_inode_data_blocks(fs, inode) == 0) {
3567                                ctx->fs_fast_symlinks_count++;
3568                                check_blocks(ctx, &pctx, block_buf);
3569                                continue;
3570                        }
3571                }
3572                else if (LINUX_S_ISFIFO (inode->i_mode) &&
3573                         e2fsck_pass1_check_device_inode(fs, inode)) {
3574                        check_immutable(ctx, &pctx);
3575                        check_size(ctx, &pctx);
3576                        ctx->fs_fifo_count++;
3577                } else if ((LINUX_S_ISSOCK (inode->i_mode)) &&
3578                           e2fsck_pass1_check_device_inode(fs, inode)) {
3579                        check_immutable(ctx, &pctx);
3580                        check_size(ctx, &pctx);
3581                        ctx->fs_sockets_count++;
3582                } else
3583                        mark_inode_bad(ctx, ino);
3584                if (inode->i_block[EXT2_IND_BLOCK])
3585                        ctx->fs_ind_count++;
3586                if (inode->i_block[EXT2_DIND_BLOCK])
3587                        ctx->fs_dind_count++;
3588                if (inode->i_block[EXT2_TIND_BLOCK])
3589                        ctx->fs_tind_count++;
3590                if (inode->i_block[EXT2_IND_BLOCK] ||
3591                    inode->i_block[EXT2_DIND_BLOCK] ||
3592                    inode->i_block[EXT2_TIND_BLOCK] ||
3593                    inode->i_file_acl) {
3594                        inodes_to_process[process_inode_count].ino = ino;
3595                        inodes_to_process[process_inode_count].inode = *inode;
3596                        process_inode_count++;
3597                } else
3598                        check_blocks(ctx, &pctx, block_buf);
3599
3600                if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3601                        return;
3602
3603                if (process_inode_count >= ctx->process_inode_size) {
3604                        process_inodes(ctx, block_buf);
3605
3606                        if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3607                                return;
3608                }
3609        }
3610        process_inodes(ctx, block_buf);
3611        ext2fs_close_inode_scan(scan);
3612        ehandler_operation(0);
3613
3614        /*
3615         * If any extended attribute blocks' reference counts need to
3616         * be adjusted, either up (ctx->refcount_extra), or down
3617         * (ctx->refcount), then fix them.
3618         */
3619        if (ctx->refcount) {
3620                adjust_extattr_refcount(ctx, ctx->refcount, block_buf, -1);
3621                ea_refcount_free(ctx->refcount);
3622                ctx->refcount = 0;
3623        }
3624        if (ctx->refcount_extra) {
3625                adjust_extattr_refcount(ctx, ctx->refcount_extra,
3626                                        block_buf, +1);
3627                ea_refcount_free(ctx->refcount_extra);
3628                ctx->refcount_extra = 0;
3629        }
3630
3631        if (ctx->invalid_bitmaps)
3632                handle_fs_bad_blocks(ctx);
3633
3634        /* We don't need the block_ea_map any more */
3635        ext2fs_free_block_bitmap(ctx->block_ea_map);
3636        ctx->block_ea_map = 0;
3637
3638        if (ctx->flags & E2F_FLAG_RESIZE_INODE) {
3639                ext2fs_block_bitmap save_bmap;
3640
3641                save_bmap = fs->block_map;
3642                fs->block_map = ctx->block_found_map;
3643                clear_problem_context(&pctx);
3644                pctx.errcode = ext2fs_create_resize_inode(fs);
3645                if (pctx.errcode) {
3646                        fix_problem(ctx, PR_1_RESIZE_INODE_CREATE, &pctx);
3647                        /* Should never get here */
3648                        ctx->flags |= E2F_FLAG_ABORT;
3649                        return;
3650                }
3651                e2fsck_read_inode(ctx, EXT2_RESIZE_INO, inode,
3652                                  "recreate inode");
3653                inode->i_mtime = time(NULL);
3654                e2fsck_write_inode(ctx, EXT2_RESIZE_INO, inode,
3655                                  "recreate inode");
3656                fs->block_map = save_bmap;
3657                ctx->flags &= ~E2F_FLAG_RESIZE_INODE;
3658        }
3659
3660        if (ctx->flags & E2F_FLAG_RESTART) {
3661                /*
3662                 * Only the master copy of the superblock and block
3663                 * group descriptors are going to be written during a
3664                 * restart, so set the superblock to be used to be the
3665                 * master superblock.
3666                 */
3667                ctx->use_superblock = 0;
3668                unwind_pass1();
3669                goto endit;
3670        }
3671
3672        if (ctx->block_dup_map) {
3673                if (ctx->options & E2F_OPT_PREEN) {
3674                        clear_problem_context(&pctx);
3675                        fix_problem(ctx, PR_1_DUP_BLOCKS_PREENSTOP, &pctx);
3676                }
3677                e2fsck_pass1_dupblocks(ctx, block_buf);
3678        }
3679        ext2fs_free_mem(&inodes_to_process);
3680endit:
3681        e2fsck_use_inode_shortcuts(ctx, 0);
3682
3683        ext2fs_free_mem(&block_buf);
3684        ext2fs_free_mem(&inode);
3685
3686}
3687
3688/*
3689 * When the inode_scan routines call this callback at the end of the
3690 * glock group, call process_inodes.
3691 */
3692static errcode_t scan_callback(ext2_filsys fs,
3693                               dgrp_t group, void * priv_data)
3694{
3695        struct scan_callback_struct *scan_struct;
3696        e2fsck_t ctx;
3697
3698        scan_struct = (struct scan_callback_struct *) priv_data;
3699        ctx = scan_struct->ctx;
3700
3701        process_inodes((e2fsck_t) fs->priv_data, scan_struct->block_buf);
3702
3703        if (ctx->progress)
3704                if ((ctx->progress)(ctx, 1, group+1,
3705                                    ctx->fs->group_desc_count))
3706                        return EXT2_ET_CANCEL_REQUESTED;
3707
3708        return 0;
3709}
3710
3711/*
3712 * Process the inodes in the "inodes to process" list.
3713 */
3714static void process_inodes(e2fsck_t ctx, char *block_buf)
3715{
3716        int                     i;
3717        struct ext2_inode       *old_stashed_inode;
3718        ext2_ino_t              old_stashed_ino;
3719        const char              *old_operation;
3720        char                    buf[80];
3721        struct problem_context  pctx;
3722
3723        /* begin process_inodes */
3724        if (process_inode_count == 0)
3725                return;
3726        old_operation = ehandler_operation(0);
3727        old_stashed_inode = ctx->stashed_inode;
3728        old_stashed_ino = ctx->stashed_ino;
3729        qsort(inodes_to_process, process_inode_count,
3730                      sizeof(struct process_inode_block), process_inode_cmp);
3731        clear_problem_context(&pctx);
3732        for (i=0; i < process_inode_count; i++) {
3733                pctx.inode = ctx->stashed_inode = &inodes_to_process[i].inode;
3734                pctx.ino = ctx->stashed_ino = inodes_to_process[i].ino;
3735                sprintf(buf, _("reading indirect blocks of inode %u"),
3736                        pctx.ino);
3737                ehandler_operation(buf);
3738                check_blocks(ctx, &pctx, block_buf);
3739                if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
3740                        break;
3741        }
3742        ctx->stashed_inode = old_stashed_inode;
3743        ctx->stashed_ino = old_stashed_ino;
3744        process_inode_count = 0;
3745        /* end process inodes */
3746
3747        ehandler_operation(old_operation);
3748}
3749
3750static int process_inode_cmp(const void *a, const void *b)
3751{
3752        const struct process_inode_block *ib_a =
3753                (const struct process_inode_block *) a;
3754        const struct process_inode_block *ib_b =
3755                (const struct process_inode_block *) b;
3756        int     ret;
3757
3758        ret = (ib_a->inode.i_block[EXT2_IND_BLOCK] -
3759               ib_b->inode.i_block[EXT2_IND_BLOCK]);
3760        if (ret == 0)
3761                ret = ib_a->inode.i_file_acl - ib_b->inode.i_file_acl;
3762        return ret;
3763}
3764
3765/*
3766 * Mark an inode as being bad in some what
3767 */
3768static void mark_inode_bad(e2fsck_t ctx, ino_t ino)
3769{
3770        struct          problem_context pctx;
3771
3772        if (!ctx->inode_bad_map) {
3773                clear_problem_context(&pctx);
3774
3775                pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3776                            _("bad inode map"), &ctx->inode_bad_map);
3777                if (pctx.errcode) {
3778                        pctx.num = 3;
3779                        fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3780                        /* Should never get here */
3781                        ctx->flags |= E2F_FLAG_ABORT;
3782                        return;
3783                }
3784        }
3785        ext2fs_mark_inode_bitmap(ctx->inode_bad_map, ino);
3786}
3787
3788
3789/*
3790 * This procedure will allocate the inode imagic table
3791 */
3792static void alloc_imagic_map(e2fsck_t ctx)
3793{
3794        struct          problem_context pctx;
3795
3796        clear_problem_context(&pctx);
3797        pctx.errcode = ext2fs_allocate_inode_bitmap(ctx->fs,
3798                                              _("imagic inode map"),
3799                                              &ctx->inode_imagic_map);
3800        if (pctx.errcode) {
3801                pctx.num = 5;
3802                fix_problem(ctx, PR_1_ALLOCATE_IBITMAP_ERROR, &pctx);
3803                /* Should never get here */
3804                ctx->flags |= E2F_FLAG_ABORT;
3805                return;
3806        }
3807}
3808
3809/*
3810 * Marks a block as in use, setting the dup_map if it's been set
3811 * already.  Called by process_block and process_bad_block.
3812 *
3813 * WARNING: Assumes checks have already been done to make sure block
3814 * is valid.  This is true in both process_block and process_bad_block.
3815 */
3816static void mark_block_used(e2fsck_t ctx, blk_t block)
3817{
3818        struct          problem_context pctx;
3819
3820        clear_problem_context(&pctx);
3821
3822        if (ext2fs_fast_test_block_bitmap(ctx->block_found_map, block)) {
3823                if (!ctx->block_dup_map) {
3824                        pctx.errcode = ext2fs_allocate_block_bitmap(ctx->fs,
3825                              _("multiply claimed block map"),
3826                              &ctx->block_dup_map);
3827                        if (pctx.errcode) {
3828                                pctx.num = 3;
3829                                fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR,
3830                                            &pctx);
3831                                /* Should never get here */
3832                                ctx->flags |= E2F_FLAG_ABORT;
3833                                return;
3834                        }
3835                }
3836                ext2fs_fast_mark_block_bitmap(ctx->block_dup_map, block);
3837        } else {
3838                ext2fs_fast_mark_block_bitmap(ctx->block_found_map, block);
3839        }
3840}
3841
3842/*
3843 * Adjust the extended attribute block's reference counts at the end
3844 * of pass 1, either by subtracting out references for EA blocks that
3845 * are still referenced in ctx->refcount, or by adding references for
3846 * EA blocks that had extra references as accounted for in
3847 * ctx->refcount_extra.
3848 */
3849static void adjust_extattr_refcount(e2fsck_t ctx, ext2_refcount_t refcount,
3850                                    char *block_buf, int adjust_sign)
3851{
3852        struct ext2_ext_attr_header     *header;
3853        struct problem_context          pctx;
3854        ext2_filsys                     fs = ctx->fs;
3855        blk_t                           blk;
3856        __u32                           should_be;
3857        int                             count;
3858
3859        clear_problem_context(&pctx);
3860
3861        ea_refcount_intr_begin(refcount);
3862        while (1) {
3863                if ((blk = ea_refcount_intr_next(refcount, &count)) == 0)
3864                        break;
3865                pctx.blk = blk;
3866                pctx.errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3867                if (pctx.errcode) {
3868                        fix_problem(ctx, PR_1_EXTATTR_READ_ABORT, &pctx);
3869                        return;
3870                }
3871                header = (struct ext2_ext_attr_header *) block_buf;
3872                pctx.blkcount = header->h_refcount;
3873                should_be = header->h_refcount + adjust_sign * count;
3874                pctx.num = should_be;
3875                if (fix_problem(ctx, PR_1_EXTATTR_REFCOUNT, &pctx)) {
3876                        header->h_refcount = should_be;
3877                        pctx.errcode = ext2fs_write_ext_attr(fs, blk,
3878                                                             block_buf);
3879                        if (pctx.errcode) {
3880                                fix_problem(ctx, PR_1_EXTATTR_WRITE, &pctx);
3881                                continue;
3882                        }
3883                }
3884        }
3885}
3886
3887/*
3888 * Handle processing the extended attribute blocks
3889 */
3890static int check_ext_attr(e2fsck_t ctx, struct problem_context *pctx,
3891                           char *block_buf)
3892{
3893        ext2_filsys fs = ctx->fs;
3894        ext2_ino_t      ino = pctx->ino;
3895        struct ext2_inode *inode = pctx->inode;
3896        blk_t           blk;
3897        char *          end;
3898        struct ext2_ext_attr_header *header;
3899        struct ext2_ext_attr_entry *entry;
3900        int             count;
3901        region_t        region;
3902
3903        blk = inode->i_file_acl;
3904        if (blk == 0)
3905                return 0;
3906
3907        /*
3908         * If the Extended attribute flag isn't set, then a non-zero
3909         * file acl means that the inode is corrupted.
3910         *
3911         * Or if the extended attribute block is an invalid block,
3912         * then the inode is also corrupted.
3913         */
3914        if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) ||
3915            (blk < fs->super->s_first_data_block) ||
3916            (blk >= fs->super->s_blocks_count)) {
3917                mark_inode_bad(ctx, ino);
3918                return 0;
3919        }
3920
3921        /* If ea bitmap hasn't been allocated, create it */
3922        if (!ctx->block_ea_map) {
3923                pctx->errcode = ext2fs_allocate_block_bitmap(fs,
3924                                                      _("ext attr block map"),
3925                                                      &ctx->block_ea_map);
3926                if (pctx->errcode) {
3927                        pctx->num = 2;
3928                        fix_problem(ctx, PR_1_ALLOCATE_BBITMAP_ERROR, pctx);
3929                        ctx->flags |= E2F_FLAG_ABORT;
3930                        return 0;
3931                }
3932        }
3933
3934        /* Create the EA refcount structure if necessary */
3935        if (!ctx->refcount) {
3936                pctx->errcode = ea_refcount_create(0, &ctx->refcount);
3937                if (pctx->errcode) {
3938                        pctx->num = 1;
3939                        fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3940                        ctx->flags |= E2F_FLAG_ABORT;
3941                        return 0;
3942                }
3943        }
3944
3945        /* Have we seen this EA block before? */
3946        if (ext2fs_fast_test_block_bitmap(ctx->block_ea_map, blk)) {
3947                if (ea_refcount_decrement(ctx->refcount, blk, 0) == 0)
3948                        return 1;
3949                /* Ooops, this EA was referenced more than it stated */
3950                if (!ctx->refcount_extra) {
3951                        pctx->errcode = ea_refcount_create(0,
3952                                           &ctx->refcount_extra);
3953                        if (pctx->errcode) {
3954                                pctx->num = 2;
3955                                fix_problem(ctx, PR_1_ALLOCATE_REFCOUNT, pctx);
3956                                ctx->flags |= E2F_FLAG_ABORT;
3957                                return 0;
3958                        }
3959                }
3960                ea_refcount_increment(ctx->refcount_extra, blk, 0);
3961                return 1;
3962        }
3963
3964        /*
3965         * OK, we haven't seen this EA block yet.  So we need to
3966         * validate it
3967         */
3968        pctx->blk = blk;
3969        pctx->errcode = ext2fs_read_ext_attr(fs, blk, block_buf);
3970        if (pctx->errcode && fix_problem(ctx, PR_1_READ_EA_BLOCK, pctx))
3971                goto clear_extattr;
3972        header = (struct ext2_ext_attr_header *) block_buf;
3973        pctx->blk = inode->i_file_acl;
3974        if (((ctx->ext_attr_ver == 1) &&
3975             (header->h_magic != EXT2_EXT_ATTR_MAGIC_v1)) ||
3976            ((ctx->ext_attr_ver == 2) &&
3977             (header->h_magic != EXT2_EXT_ATTR_MAGIC))) {
3978                if (fix_problem(ctx, PR_1_BAD_EA_BLOCK, pctx))
3979                        goto clear_extattr;
3980        }
3981
3982        if (header->h_blocks != 1) {
3983                if (fix_problem(ctx, PR_1_EA_MULTI_BLOCK, pctx))
3984                        goto clear_extattr;
3985        }
3986
3987        region = region_create(0, fs->blocksize);
3988        if (!region) {
3989                fix_problem(ctx, PR_1_EA_ALLOC_REGION, pctx);
3990                ctx->flags |= E2F_FLAG_ABORT;
3991                return 0;
3992        }
3993        if (region_allocate(region, 0, sizeof(struct ext2_ext_attr_header))) {
3994                if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
3995                        goto clear_extattr;
3996        }
3997
3998        entry = (struct ext2_ext_attr_entry *)(header+1);
3999        end = block_buf + fs->blocksize;
4000        while ((char *)entry < end && *(__u32 *)entry) {
4001                if (region_allocate(region, (char *)entry - (char *)header,
4002                                   EXT2_EXT_ATTR_LEN(entry->e_name_len))) {
4003                        if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4004                                goto clear_extattr;
4005                }
4006                if ((ctx->ext_attr_ver == 1 &&
4007                     (entry->e_name_len == 0 || entry->e_name_index != 0)) ||
4008                    (ctx->ext_attr_ver == 2 &&
4009                     entry->e_name_index == 0)) {
4010                        if (fix_problem(ctx, PR_1_EA_BAD_NAME, pctx))
4011                                goto clear_extattr;
4012                }
4013                if (entry->e_value_block != 0) {
4014                        if (fix_problem(ctx, PR_1_EA_BAD_VALUE, pctx))
4015                                goto clear_extattr;
4016                }
4017                if (entry->e_value_size &&
4018                    region_allocate(region, entry->e_value_offs,
4019                                    EXT2_EXT_ATTR_SIZE(entry->e_value_size))) {
4020                        if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4021                                goto clear_extattr;
4022                }
4023                entry = EXT2_EXT_ATTR_NEXT(entry);
4024        }
4025        if (region_allocate(region, (char *)entry - (char *)header, 4)) {
4026                if (fix_problem(ctx, PR_1_EA_ALLOC_COLLISION, pctx))
4027                        goto clear_extattr;
4028        }
4029        region_free(region);
4030
4031        count = header->h_refcount - 1;
4032        if (count)
4033                ea_refcount_store(ctx->refcount, blk, count);
4034        mark_block_used(ctx, blk);
4035        ext2fs_fast_mark_block_bitmap(ctx->block_ea_map, blk);
4036
4037        return 1;
4038
4039clear_extattr:
4040        inode->i_file_acl = 0;
4041        e2fsck_write_inode(ctx, ino, inode, "check_ext_attr");
4042        return 0;
4043}
4044
4045/* Returns 1 if bad htree, 0 if OK */
4046static int handle_htree(e2fsck_t ctx, struct problem_context *pctx,
4047                        ext2_ino_t ino FSCK_ATTR((unused)),
4048                        struct ext2_inode *inode,
4049                        char *block_buf)
4050{
4051        struct ext2_dx_root_info        *root;
4052        ext2_filsys                     fs = ctx->fs;
4053        errcode_t                       retval;
4054        blk_t                           blk;
4055
4056        if ((!LINUX_S_ISDIR(inode->i_mode) &&
4057             fix_problem(ctx, PR_1_HTREE_NODIR, pctx)) ||
4058            (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) &&
4059             fix_problem(ctx, PR_1_HTREE_SET, pctx)))
4060                return 1;
4061
4062        blk = inode->i_block[0];
4063        if (((blk == 0) ||
4064             (blk < fs->super->s_first_data_block) ||
4065             (blk >= fs->super->s_blocks_count)) &&
4066            fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4067                return 1;
4068
4069        retval = io_channel_read_blk(fs->io, blk, 1, block_buf);
4070        if (retval && fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4071                return 1;
4072
4073        /* XXX should check that beginning matches a directory */
4074        root = (struct ext2_dx_root_info *) (block_buf + 24);
4075
4076        if ((root->reserved_zero || root->info_length < 8) &&
4077            fix_problem(ctx, PR_1_HTREE_BADROOT, pctx))
4078                return 1;
4079
4080        pctx->num = root->hash_version;
4081        if ((root->hash_version != EXT2_HASH_LEGACY) &&
4082            (root->hash_version != EXT2_HASH_HALF_MD4) &&
4083            (root->hash_version != EXT2_HASH_TEA) &&
4084            fix_problem(ctx, PR_1_HTREE_HASHV, pctx))
4085                return 1;
4086
4087        if ((root->unused_flags & EXT2_HASH_FLAG_INCOMPAT) &&
4088            fix_problem(ctx, PR_1_HTREE_INCOMPAT, pctx))
4089                return 1;
4090
4091        pctx->num = root->indirect_levels;
4092        if ((root->indirect_levels > 1) &&
4093            fix_problem(ctx, PR_1_HTREE_DEPTH, pctx))
4094                return 1;
4095
4096        return 0;
4097}
4098
4099/*
4100 * This subroutine is called on each inode to account for all of the
4101 * blocks used by that inode.
4102 */
4103static void check_blocks(e2fsck_t ctx, struct problem_context *pctx,
4104                         char *block_buf)
4105{
4106        ext2_filsys fs = ctx->fs;
4107        struct process_block_struct_1 pb;
4108        ext2_ino_t      ino = pctx->ino;
4109        struct ext2_inode *inode = pctx->inode;
4110        int             bad_size = 0;
4111        int             dirty_inode = 0;
4112        __u64           size;
4113
4114        pb.ino = ino;
4115        pb.num_blocks = 0;
4116        pb.last_block = -1;
4117        pb.num_illegal_blocks = 0;
4118        pb.suppress = 0; pb.clear = 0;
4119        pb.fragmented = 0;
4120        pb.compressed = 0;
4121        pb.previous_block = 0;
4122        pb.is_dir = LINUX_S_ISDIR(inode->i_mode);
4123        pb.is_reg = LINUX_S_ISREG(inode->i_mode);
4124        pb.max_blocks = 1 << (31 - fs->super->s_log_block_size);
4125        pb.inode = inode;
4126        pb.pctx = pctx;
4127        pb.ctx = ctx;
4128        pctx->ino = ino;
4129        pctx->errcode = 0;
4130
4131        if (inode->i_flags & EXT2_COMPRBLK_FL) {
4132                if (fs->super->s_feature_incompat &
4133                    EXT2_FEATURE_INCOMPAT_COMPRESSION)
4134                        pb.compressed = 1;
4135                else {
4136                        if (fix_problem(ctx, PR_1_COMPR_SET, pctx)) {
4137                                inode->i_flags &= ~EXT2_COMPRBLK_FL;
4138                                dirty_inode++;
4139                        }
4140                }
4141        }
4142
4143        if (inode->i_file_acl && check_ext_attr(ctx, pctx, block_buf))
4144                pb.num_blocks++;
4145
4146        if (ext2fs_inode_has_valid_blocks(inode))
4147                pctx->errcode = ext2fs_block_iterate2(fs, ino,
4148                                       pb.is_dir ? BLOCK_FLAG_HOLE : 0,
4149                                       block_buf, process_block, &pb);
4150        end_problem_latch(ctx, PR_LATCH_BLOCK);
4151        end_problem_latch(ctx, PR_LATCH_TOOBIG);
4152        if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
4153                goto out;
4154        if (pctx->errcode)
4155                fix_problem(ctx, PR_1_BLOCK_ITERATE, pctx);
4156
4157        if (pb.fragmented && pb.num_blocks < fs->super->s_blocks_per_group)
4158                ctx->fs_fragmented++;
4159
4160        if (pb.clear) {
4161                inode->i_links_count = 0;
4162                ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4163                inode->i_dtime = time(NULL);
4164                dirty_inode++;
4165                ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4166                ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4167                ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4168                /*
4169                 * The inode was probably partially accounted for
4170                 * before processing was aborted, so we need to
4171                 * restart the pass 1 scan.
4172                 */
4173                ctx->flags |= E2F_FLAG_RESTART;
4174                goto out;
4175        }
4176
4177        if (inode->i_flags & EXT2_INDEX_FL) {
4178                if (handle_htree(ctx, pctx, ino, inode, block_buf)) {
4179                        inode->i_flags &= ~EXT2_INDEX_FL;
4180                        dirty_inode++;
4181                } else {
4182#ifdef ENABLE_HTREE
4183                        e2fsck_add_dx_dir(ctx, ino, pb.last_block+1);
4184#endif
4185                }
4186        }
4187        if (ctx->dirs_to_hash && pb.is_dir &&
4188            !(inode->i_flags & EXT2_INDEX_FL) &&
4189            ((inode->i_size / fs->blocksize) >= 3))
4190                ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
4191
4192        if (!pb.num_blocks && pb.is_dir) {
4193                if (fix_problem(ctx, PR_1_ZERO_LENGTH_DIR, pctx)) {
4194                        inode->i_links_count = 0;
4195                        ext2fs_icount_store(ctx->inode_link_info, ino, 0);
4196                        inode->i_dtime = time(NULL);
4197                        dirty_inode++;
4198                        ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
4199                        ext2fs_unmark_inode_bitmap(ctx->inode_reg_map, ino);
4200                        ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
4201                        ctx->fs_directory_count--;
4202                        goto out;
4203                }
4204        }
4205
4206        pb.num_blocks *= (fs->blocksize / 512);
4207
4208        if (pb.is_dir) {
4209                int nblock = inode->i_size >> EXT2_BLOCK_SIZE_BITS(fs->super);
4210                if (nblock > (pb.last_block + 1))
4211                        bad_size = 1;
4212                else if (nblock < (pb.last_block + 1)) {
4213                        if (((pb.last_block + 1) - nblock) >
4214                            fs->super->s_prealloc_dir_blocks)
4215                                bad_size = 2;
4216                }
4217        } else {
4218                size = EXT2_I_SIZE(inode);
4219                if ((pb.last_block >= 0) &&
4220                    (size < (__u64) pb.last_block * fs->blocksize))
4221                        bad_size = 3;
4222                else if (size > ext2_max_sizes[fs->super->s_log_block_size])
4223                        bad_size = 4;
4224        }
4225        /* i_size for symlinks is checked elsewhere */
4226        if (bad_size && !LINUX_S_ISLNK(inode->i_mode)) {
4227                pctx->num = (pb.last_block+1) * fs->blocksize;
4228                if (fix_problem(ctx, PR_1_BAD_I_SIZE, pctx)) {
4229                        inode->i_size = pctx->num;
4230                        if (!LINUX_S_ISDIR(inode->i_mode))
4231                                inode->i_size_high = pctx->num >> 32;
4232                        dirty_inode++;
4233                }
4234                pctx->num = 0;
4235        }
4236        if (LINUX_S_ISREG(inode->i_mode) &&
4237            (inode->i_size_high || inode->i_size & 0x80000000UL))
4238                ctx->large_files++;
4239        if (pb.num_blocks != inode->i_blocks) {
4240                pctx->num = pb.num_blocks;
4241                if (fix_problem(ctx, PR_1_BAD_I_BLOCKS, pctx)) {
4242                        inode->i_blocks = pb.num_blocks;
4243                        dirty_inode++;
4244                }
4245                pctx->num = 0;
4246        }
4247out:
4248        if (dirty_inode)
4249                e2fsck_write_inode(ctx, ino, inode, "check_blocks");
4250}
4251
4252
4253/*
4254 * This is a helper function for check_blocks().
4255 */
4256static int process_block(ext2_filsys fs,
4257                  blk_t *block_nr,
4258                  e2_blkcnt_t blockcnt,
4259                  blk_t ref_block FSCK_ATTR((unused)),
4260                  int ref_offset FSCK_ATTR((unused)),
4261                  void *priv_data)
4262{
4263        struct process_block_struct_1 *p;
4264        struct problem_context *pctx;
4265        blk_t   blk = *block_nr;
4266        int     ret_code = 0;
4267        int     problem = 0;
4268        e2fsck_t        ctx;
4269
4270        p = (struct process_block_struct_1 *) priv_data;
4271        pctx = p->pctx;
4272        ctx = p->ctx;
4273
4274        if (p->compressed && (blk == EXT2FS_COMPRESSED_BLKADDR)) {
4275                /* todo: Check that the comprblk_fl is high, that the
4276                   blkaddr pattern looks right (all non-holes up to
4277                   first EXT2FS_COMPRESSED_BLKADDR, then all
4278                   EXT2FS_COMPRESSED_BLKADDR up to end of cluster),
4279                   that the feature_incompat bit is high, and that the
4280                   inode is a regular file.  If we're doing a "full
4281                   check" (a concept introduced to e2fsck by e2compr,
4282                   meaning that we look at data blocks as well as
4283                   metadata) then call some library routine that
4284                   checks the compressed data.  I'll have to think
4285                   about this, because one particularly important
4286                   problem to be able to fix is to recalculate the
4287                   cluster size if necessary.  I think that perhaps
4288                   we'd better do most/all e2compr-specific checks
4289                   separately, after the non-e2compr checks.  If not
4290                   doing a full check, it may be useful to test that
4291                   the personality is linux; e.g. if it isn't then
4292                   perhaps this really is just an illegal block. */
4293                return 0;
4294        }
4295
4296        if (blk == 0) {
4297                if (p->is_dir == 0) {
4298                        /*
4299                         * Should never happen, since only directories
4300                         * get called with BLOCK_FLAG_HOLE
4301                         */
4302#ifdef DEBUG_E2FSCK
4303                        printf("process_block() called with blk == 0, "
4304                               "blockcnt=%d, inode %lu???\n",
4305                               blockcnt, p->ino);
4306#endif
4307                        return 0;
4308                }
4309                if (blockcnt < 0)
4310                        return 0;
4311                if (blockcnt * fs->blocksize < p->inode->i_size) {
4312                        goto mark_dir;
4313                }
4314                return 0;
4315        }
4316
4317        /*
4318         * Simplistic fragmentation check.  We merely require that the
4319         * file be contiguous.  (Which can never be true for really
4320         * big files that are greater than a block group.)
4321         */
4322        if (!HOLE_BLKADDR(p->previous_block)) {
4323                if (p->previous_block+1 != blk)
4324                        p->fragmented = 1;
4325        }
4326        p->previous_block = blk;
4327
4328        if (p->is_dir && blockcnt > (1 << (21 - fs->super->s_log_block_size)))
4329                problem = PR_1_TOOBIG_DIR;
4330        if (p->is_reg && p->num_blocks+1 >= p->max_blocks)
4331                problem = PR_1_TOOBIG_REG;
4332        if (!p->is_dir && !p->is_reg && blockcnt > 0)
4333                problem = PR_1_TOOBIG_SYMLINK;
4334
4335        if (blk < fs->super->s_first_data_block ||
4336            blk >= fs->super->s_blocks_count)
4337                problem = PR_1_ILLEGAL_BLOCK_NUM;
4338
4339        if (problem) {
4340                p->num_illegal_blocks++;
4341                if (!p->suppress && (p->num_illegal_blocks % 12) == 0) {
4342                        if (fix_problem(ctx, PR_1_TOO_MANY_BAD_BLOCKS, pctx)) {
4343                                p->clear = 1;
4344                                return BLOCK_ABORT;
4345                        }
4346                        if (fix_problem(ctx, PR_1_SUPPRESS_MESSAGES, pctx)) {
4347                                p->suppress = 1;
4348                                set_latch_flags(PR_LATCH_BLOCK,
4349                                                PRL_SUPPRESS, 0);
4350                        }
4351                }
4352                pctx->blk = blk;
4353                pctx->blkcount = blockcnt;
4354                if (fix_problem(ctx, problem, pctx)) {
4355                        blk = *block_nr = 0;
4356                        ret_code = BLOCK_CHANGED;
4357                        goto mark_dir;
4358                } else
4359                        return 0;
4360        }
4361
4362        if (p->ino == EXT2_RESIZE_INO) {
4363                /*
4364                 * The resize inode has already be sanity checked
4365                 * during pass #0 (the superblock checks).  All we
4366                 * have to do is mark the double indirect block as
4367                 * being in use; all of the other blocks are handled
4368                 * by mark_table_blocks()).
4369                 */
4370                if (blockcnt == BLOCK_COUNT_DIND)
4371                        mark_block_used(ctx, blk);
4372        } else
4373                mark_block_used(ctx, blk);
4374        p->num_blocks++;
4375        if (blockcnt >= 0)
4376                p->last_block = blockcnt;
4377mark_dir:
4378        if (p->is_dir && (blockcnt >= 0)) {
4379                pctx->errcode = ext2fs_add_dir_block(fs->dblist, p->ino,
4380                                                    blk, blockcnt);
4381                if (pctx->errcode) {
4382                        pctx->blk = blk;
4383                        pctx->num = blockcnt;
4384                        fix_problem(ctx, PR_1_ADD_DBLOCK, pctx);
4385                        /* Should never get here */
4386                        ctx->flags |= E2F_FLAG_ABORT;
4387                        return BLOCK_ABORT;
4388                }
4389        }
4390        return ret_code;
4391}
4392
4393static int process_bad_block(ext2_filsys fs FSCK_ATTR((unused)),
4394                      blk_t *block_nr,
4395                      e2_blkcnt_t blockcnt,
4396                      blk_t ref_block FSCK_ATTR((unused)),
4397                      int ref_offset FSCK_ATTR((unused)),
4398                      void *priv_data EXT2FS_ATTR((unused)))
4399{
4400        /*
4401         * Note: This function processes blocks for the bad blocks
4402         * inode, which is never compressed.  So we don't use HOLE_BLKADDR().
4403         */
4404
4405        printf("Unrecoverable Error: Found %"PRIi64" bad blocks starting at block number: %u\n", blockcnt, *block_nr);
4406        return BLOCK_ERROR;
4407}
4408
4409/*
4410 * This routine gets called at the end of pass 1 if bad blocks are
4411 * detected in the superblock, group descriptors, inode_bitmaps, or
4412 * block bitmaps.  At this point, all of the blocks have been mapped
4413 * out, so we can try to allocate new block(s) to replace the bad
4414 * blocks.
4415 */
4416static void handle_fs_bad_blocks(e2fsck_t ctx)
4417{
4418        printf("Bad blocks detected on your filesystem\n"
4419                "You should get your data off as the device will soon die\n");
4420}
4421
4422/*
4423 * This routine marks all blocks which are used by the superblock,
4424 * group descriptors, inode bitmaps, and block bitmaps.
4425 */
4426static void mark_table_blocks(e2fsck_t ctx)
4427{
4428        ext2_filsys fs = ctx->fs;
4429        blk_t   block, b;
4430        dgrp_t  i;
4431        int     j;
4432        struct problem_context pctx;
4433
4434        clear_problem_context(&pctx);
4435
4436        block = fs->super->s_first_data_block;
4437        for (i = 0; i < fs->group_desc_count; i++) {
4438                pctx.group = i;
4439
4440                ext2fs_reserve_super_and_bgd(fs, i, ctx->block_found_map);
4441
4442                /*
4443                 * Mark the blocks used for the inode table
4444                 */
4445                if (fs->group_desc[i].bg_inode_table) {
4446                        for (j = 0, b = fs->group_desc[i].bg_inode_table;
4447                             j < fs->inode_blocks_per_group;
4448                             j++, b++) {
4449                                if (ext2fs_test_block_bitmap(ctx->block_found_map,
4450                                                             b)) {
4451                                        pctx.blk = b;
4452                                        if (fix_problem(ctx,
4453                                                PR_1_ITABLE_CONFLICT, &pctx)) {
4454                                                ctx->invalid_inode_table_flag[i]++;
4455                                                ctx->invalid_bitmaps++;
4456                                        }
4457                                } else {
4458                                    ext2fs_mark_block_bitmap(ctx->block_found_map,
4459                                                             b);
4460                                }
4461                        }
4462                }
4463
4464                /*
4465                 * Mark block used for the block bitmap
4466                 */
4467                if (fs->group_desc[i].bg_block_bitmap) {
4468                        if (ext2fs_test_block_bitmap(ctx->block_found_map,
4469                                     fs->group_desc[i].bg_block_bitmap)) {
4470                                pctx.blk = fs->group_desc[i].bg_block_bitmap;
4471                                if (fix_problem(ctx, PR_1_BB_CONFLICT, &pctx)) {
4472                                        ctx->invalid_block_bitmap_flag[i]++;
4473                                        ctx->invalid_bitmaps++;
4474                                }
4475                        } else {
4476                            ext2fs_mark_block_bitmap(ctx->block_found_map,
4477                                     fs->group_desc[i].bg_block_bitmap);
4478                    }
4479
4480                }
4481                /*
4482                 * Mark block used for the inode bitmap
4483                 */
4484                if (fs->group_desc[i].bg_inode_bitmap) {
4485                        if (ext2fs_test_block_bitmap(ctx->block_found_map,
4486                                     fs->group_desc[i].bg_inode_bitmap)) {
4487                                pctx.blk = fs->group_desc[i].bg_inode_bitmap;
4488                                if (fix_problem(ctx, PR_1_IB_CONFLICT, &pctx)) {
4489                                        ctx->invalid_inode_bitmap_flag[i]++;
4490                                        ctx->invalid_bitmaps++;
4491                                }
4492                        } else {
4493                            ext2fs_mark_block_bitmap(ctx->block_found_map,
4494                                     fs->group_desc[i].bg_inode_bitmap);
4495                        }
4496                }
4497                block += fs->super->s_blocks_per_group;
4498        }
4499}
4500
4501/*
4502 * Thes subroutines short circuits ext2fs_get_blocks and
4503 * ext2fs_check_directory; we use them since we already have the inode
4504 * structure, so there's no point in letting the ext2fs library read
4505 * the inode again.
4506 */
4507static errcode_t pass1_get_blocks(ext2_filsys fs, ext2_ino_t ino,
4508                                  blk_t *blocks)
4509{
4510        e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4511        int     i;
4512
4513        if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4514                return EXT2_ET_CALLBACK_NOTHANDLED;
4515
4516        for (i=0; i < EXT2_N_BLOCKS; i++)
4517                blocks[i] = ctx->stashed_inode->i_block[i];
4518        return 0;
4519}
4520
4521static errcode_t pass1_read_inode(ext2_filsys fs, ext2_ino_t ino,
4522                                  struct ext2_inode *inode)
4523{
4524        e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4525
4526        if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4527                return EXT2_ET_CALLBACK_NOTHANDLED;
4528        *inode = *ctx->stashed_inode;
4529        return 0;
4530}
4531
4532static errcode_t pass1_write_inode(ext2_filsys fs, ext2_ino_t ino,
4533                            struct ext2_inode *inode)
4534{
4535        e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4536
4537        if ((ino == ctx->stashed_ino) && ctx->stashed_inode)
4538                *ctx->stashed_inode = *inode;
4539        return EXT2_ET_CALLBACK_NOTHANDLED;
4540}
4541
4542static errcode_t pass1_check_directory(ext2_filsys fs, ext2_ino_t ino)
4543{
4544        e2fsck_t ctx = (e2fsck_t) fs->priv_data;
4545
4546        if ((ino != ctx->stashed_ino) || !ctx->stashed_inode)
4547                return EXT2_ET_CALLBACK_NOTHANDLED;
4548
4549        if (!LINUX_S_ISDIR(ctx->stashed_inode->i_mode))
4550                return EXT2_ET_NO_DIRECTORY;
4551        return 0;
4552}
4553
4554void e2fsck_use_inode_shortcuts(e2fsck_t ctx, int bool)
4555{
4556        ext2_filsys fs = ctx->fs;
4557
4558        if (bool) {
4559                fs->get_blocks = pass1_get_blocks;
4560                fs->check_directory = pass1_check_directory;
4561                fs->read_inode = pass1_read_inode;
4562                fs->write_inode = pass1_write_inode;
4563                ctx->stashed_ino = 0;
4564        } else {
4565                fs->get_blocks = 0;
4566                fs->check_directory = 0;
4567                fs->read_inode = 0;
4568                fs->write_inode = 0;
4569        }
4570}
4571
4572/*
4573 * pass1b.c --- Pass #1b of e2fsck
4574 *
4575 * This file contains pass1B, pass1C, and pass1D of e2fsck.  They are
4576 * only invoked if pass 1 discovered blocks which are in use by more
4577 * than one inode.
4578 *
4579 * Pass1B scans the data blocks of all the inodes again, generating a
4580 * complete list of duplicate blocks and which inodes have claimed
4581 * them.
4582 *
4583 * Pass1C does a tree-traversal of the filesystem, to determine the
4584 * parent directories of these inodes.  This step is necessary so that
4585 * e2fsck can print out the pathnames of affected inodes.
4586 *
4587 * Pass1D is a reconciliation pass.  For each inode with duplicate
4588 * blocks, the user is prompted if s/he would like to clone the file
4589 * (so that the file gets a fresh copy of the duplicated blocks) or
4590 * simply to delete the file.
4591 *
4592 */
4593
4594
4595/* Needed for architectures where sizeof(int) != sizeof(void *) */
4596#define INT_TO_VOIDPTR(val)  ((void *)(intptr_t)(val))
4597#define VOIDPTR_TO_INT(ptr)  ((int)(intptr_t)(ptr))
4598
4599/* Define an extension to the ext2 library's block count information */
4600#define BLOCK_COUNT_EXTATTR     (-5)
4601
4602struct block_el {
4603        blk_t   block;
4604        struct block_el *next;
4605};
4606
4607struct inode_el {
4608        ext2_ino_t      inode;
4609        struct inode_el *next;
4610};
4611
4612struct dup_block {
4613        int             num_bad;
4614        struct inode_el *inode_list;
4615};
4616
4617/*
4618 * This structure stores information about a particular inode which
4619 * is sharing blocks with other inodes.  This information is collected
4620 * to display to the user, so that the user knows what files he or she
4621 * is dealing with, when trying to decide how to resolve the conflict
4622 * of multiply-claimed blocks.
4623 */
4624struct dup_inode {
4625        ext2_ino_t              dir;
4626        int                     num_dupblocks;
4627        struct ext2_inode       inode;
4628        struct block_el         *block_list;
4629};
4630
4631static int process_pass1b_block(ext2_filsys fs, blk_t   *blocknr,
4632                                e2_blkcnt_t blockcnt, blk_t ref_blk,
4633                                int ref_offset, void *priv_data);
4634static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
4635                        struct dup_inode *dp, char *block_buf);
4636static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
4637                      struct dup_inode *dp, char* block_buf);
4638static int check_if_fs_block(e2fsck_t ctx, blk_t test_blk);
4639
4640static void pass1b(e2fsck_t ctx, char *block_buf);
4641static void pass1c(e2fsck_t ctx, char *block_buf);
4642static void pass1d(e2fsck_t ctx, char *block_buf);
4643
4644static int dup_inode_count = 0;
4645
4646static dict_t blk_dict, ino_dict;
4647
4648static ext2fs_inode_bitmap inode_dup_map;
4649
4650static int dict_int_cmp(const void *a, const void *b)
4651{
4652        intptr_t        ia, ib;
4653
4654        ia = (intptr_t)a;
4655        ib = (intptr_t)b;
4656
4657        return (ia-ib);
4658}
4659
4660/*
4661 * Add a duplicate block record
4662 */
4663static void add_dupe(e2fsck_t ctx, ext2_ino_t ino, blk_t blk,
4664                     struct ext2_inode *inode)
4665{
4666        dnode_t *n;
4667        struct dup_block        *db;
4668        struct dup_inode        *di;
4669        struct block_el         *blk_el;
4670        struct inode_el         *ino_el;
4671
4672        n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
4673        if (n)
4674                db = (struct dup_block *) dnode_get(n);
4675        else {
4676                db = (struct dup_block *) e2fsck_allocate_memory(ctx,
4677                         sizeof(struct dup_block), "duplicate block header");
4678                db->num_bad = 0;
4679                db->inode_list = 0;
4680                dict_alloc_insert(&blk_dict, INT_TO_VOIDPTR(blk), db);
4681        }
4682        ino_el = (struct inode_el *) e2fsck_allocate_memory(ctx,
4683                         sizeof(struct inode_el), "inode element");
4684        ino_el->inode = ino;
4685        ino_el->next = db->inode_list;
4686        db->inode_list = ino_el;
4687        db->num_bad++;
4688
4689        n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino));
4690        if (n)
4691                di = (struct dup_inode *) dnode_get(n);
4692        else {
4693                di = (struct dup_inode *) e2fsck_allocate_memory(ctx,
4694                         sizeof(struct dup_inode), "duplicate inode header");
4695                di->dir = (ino == EXT2_ROOT_INO) ? EXT2_ROOT_INO : 0;
4696                di->num_dupblocks = 0;
4697                di->block_list = 0;
4698                di->inode = *inode;
4699                dict_alloc_insert(&ino_dict, INT_TO_VOIDPTR(ino), di);
4700        }
4701        blk_el = (struct block_el *) e2fsck_allocate_memory(ctx,
4702                         sizeof(struct block_el), "block element");
4703        blk_el->block = blk;
4704        blk_el->next = di->block_list;
4705        di->block_list = blk_el;
4706        di->num_dupblocks++;
4707}
4708
4709/*
4710 * Free a duplicate inode record
4711 */
4712static void inode_dnode_free(dnode_t *node)
4713{
4714        struct dup_inode        *di;
4715        struct block_el         *p, *next;
4716
4717        di = (struct dup_inode *) dnode_get(node);
4718        for (p = di->block_list; p; p = next) {
4719                next = p->next;
4720                free(p);
4721        }
4722        free(node);
4723}
4724
4725/*
4726 * Free a duplicate block record
4727 */
4728static void block_dnode_free(dnode_t *node)
4729{
4730        struct dup_block        *db;
4731        struct inode_el         *p, *next;
4732
4733        db = (struct dup_block *) dnode_get(node);
4734        for (p = db->inode_list; p; p = next) {
4735                next = p->next;
4736                free(p);
4737        }
4738        free(node);
4739}
4740
4741
4742/*
4743 * Main procedure for handling duplicate blocks
4744 */
4745void e2fsck_pass1_dupblocks(e2fsck_t ctx, char *block_buf)
4746{
4747        ext2_filsys             fs = ctx->fs;
4748        struct problem_context  pctx;
4749
4750        clear_problem_context(&pctx);
4751
4752        pctx.errcode = ext2fs_allocate_inode_bitmap(fs,
4753                      _("multiply claimed inode map"), &inode_dup_map);
4754        if (pctx.errcode) {
4755                fix_problem(ctx, PR_1B_ALLOCATE_IBITMAP_ERROR, &pctx);
4756                ctx->flags |= E2F_FLAG_ABORT;
4757                return;
4758        }
4759
4760        dict_init(&ino_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4761        dict_init(&blk_dict, DICTCOUNT_T_MAX, dict_int_cmp);
4762        dict_set_allocator(&ino_dict, inode_dnode_free);
4763        dict_set_allocator(&blk_dict, block_dnode_free);
4764
4765        pass1b(ctx, block_buf);
4766        pass1c(ctx, block_buf);
4767        pass1d(ctx, block_buf);
4768
4769        /*
4770         * Time to free all of the accumulated data structures that we
4771         * don't need anymore.
4772         */
4773        dict_free_nodes(&ino_dict);
4774        dict_free_nodes(&blk_dict);
4775}
4776
4777/*
4778 * Scan the inodes looking for inodes that contain duplicate blocks.
4779 */
4780struct process_block_struct_1b {
4781        e2fsck_t        ctx;
4782        ext2_ino_t      ino;
4783        int             dup_blocks;
4784        struct ext2_inode *inode;
4785        struct problem_context *pctx;
4786};
4787
4788static void pass1b(e2fsck_t ctx, char *block_buf)
4789{
4790        ext2_filsys fs = ctx->fs;
4791        ext2_ino_t ino;
4792        struct ext2_inode inode;
4793        ext2_inode_scan scan;
4794        struct process_block_struct_1b pb;
4795        struct problem_context pctx;
4796
4797        clear_problem_context(&pctx);
4798
4799        if (!(ctx->options & E2F_OPT_PREEN))
4800                fix_problem(ctx, PR_1B_PASS_HEADER, &pctx);
4801        pctx.errcode = ext2fs_open_inode_scan(fs, ctx->inode_buffer_blocks,
4802                                              &scan);
4803        if (pctx.errcode) {
4804                fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4805                ctx->flags |= E2F_FLAG_ABORT;
4806                return;
4807        }
4808        ctx->stashed_inode = &inode;
4809        pb.ctx = ctx;
4810        pb.pctx = &pctx;
4811        pctx.str = "pass1b";
4812        while (1) {
4813                pctx.errcode = ext2fs_get_next_inode(scan, &ino, &inode);
4814                if (pctx.errcode == EXT2_ET_BAD_BLOCK_IN_INODE_TABLE)
4815                        continue;
4816                if (pctx.errcode) {
4817                        fix_problem(ctx, PR_1B_ISCAN_ERROR, &pctx);
4818                        ctx->flags |= E2F_FLAG_ABORT;
4819                        return;
4820                }
4821                if (!ino)
4822                        break;
4823                pctx.ino = ctx->stashed_ino = ino;
4824                if ((ino != EXT2_BAD_INO) &&
4825                    !ext2fs_test_inode_bitmap(ctx->inode_used_map, ino))
4826                        continue;
4827
4828                pb.ino = ino;
4829                pb.dup_blocks = 0;
4830                pb.inode = &inode;
4831
4832                if (ext2fs_inode_has_valid_blocks(&inode) ||
4833                    (ino == EXT2_BAD_INO))
4834                        pctx.errcode = ext2fs_block_iterate2(fs, ino,
4835                                     0, block_buf, process_pass1b_block, &pb);
4836                if (inode.i_file_acl)
4837                        process_pass1b_block(fs, &inode.i_file_acl,
4838                                             BLOCK_COUNT_EXTATTR, 0, 0, &pb);
4839                if (pb.dup_blocks) {
4840                        end_problem_latch(ctx, PR_LATCH_DBLOCK);
4841                        if (ino >= EXT2_FIRST_INODE(fs->super) ||
4842                            ino == EXT2_ROOT_INO)
4843                                dup_inode_count++;
4844                }
4845                if (pctx.errcode)
4846                        fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
4847        }
4848        ext2fs_close_inode_scan(scan);
4849        e2fsck_use_inode_shortcuts(ctx, 0);
4850}
4851
4852static int process_pass1b_block(ext2_filsys fs FSCK_ATTR((unused)),
4853                                blk_t   *block_nr,
4854                                e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
4855                                blk_t ref_blk FSCK_ATTR((unused)),
4856                                int ref_offset FSCK_ATTR((unused)),
4857                                void *priv_data)
4858{
4859        struct process_block_struct_1b *p;
4860        e2fsck_t ctx;
4861
4862        if (HOLE_BLKADDR(*block_nr))
4863                return 0;
4864        p = (struct process_block_struct_1b *) priv_data;
4865        ctx = p->ctx;
4866
4867        if (!ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr))
4868                return 0;
4869
4870        /* OK, this is a duplicate block */
4871        if (p->ino != EXT2_BAD_INO) {
4872                p->pctx->blk = *block_nr;
4873                fix_problem(ctx, PR_1B_DUP_BLOCK, p->pctx);
4874        }
4875        p->dup_blocks++;
4876        ext2fs_mark_inode_bitmap(inode_dup_map, p->ino);
4877
4878        add_dupe(ctx, p->ino, *block_nr, p->inode);
4879
4880        return 0;
4881}
4882
4883/*
4884 * Pass 1c: Scan directories for inodes with duplicate blocks.  This
4885 * is used so that we can print pathnames when prompting the user for
4886 * what to do.
4887 */
4888struct search_dir_struct {
4889        int             count;
4890        ext2_ino_t      first_inode;
4891        ext2_ino_t      max_inode;
4892};
4893
4894static int search_dirent_proc(ext2_ino_t dir, int entry,
4895                              struct ext2_dir_entry *dirent,
4896                              int offset FSCK_ATTR((unused)),
4897                              int blocksize FSCK_ATTR((unused)),
4898                              char *buf FSCK_ATTR((unused)),
4899                              void *priv_data)
4900{
4901        struct search_dir_struct *sd;
4902        struct dup_inode        *p;
4903        dnode_t                 *n;
4904
4905        sd = (struct search_dir_struct *) priv_data;
4906
4907        if (dirent->inode > sd->max_inode)
4908                /* Should abort this inode, but not everything */
4909                return 0;
4910
4911        if ((dirent->inode < sd->first_inode) || (entry < DIRENT_OTHER_FILE) ||
4912            !ext2fs_test_inode_bitmap(inode_dup_map, dirent->inode))
4913                return 0;
4914
4915        n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(dirent->inode));
4916        if (!n)
4917                return 0;
4918        p = (struct dup_inode *) dnode_get(n);
4919        p->dir = dir;
4920        sd->count--;
4921
4922        return sd->count ? 0 : DIRENT_ABORT;
4923}
4924
4925
4926static void pass1c(e2fsck_t ctx, char *block_buf)
4927{
4928        ext2_filsys fs = ctx->fs;
4929        struct search_dir_struct sd;
4930        struct problem_context pctx;
4931
4932        clear_problem_context(&pctx);
4933
4934        if (!(ctx->options & E2F_OPT_PREEN))
4935                fix_problem(ctx, PR_1C_PASS_HEADER, &pctx);
4936
4937        /*
4938         * Search through all directories to translate inodes to names
4939         * (by searching for the containing directory for that inode.)
4940         */
4941        sd.count = dup_inode_count;
4942        sd.first_inode = EXT2_FIRST_INODE(fs->super);
4943        sd.max_inode = fs->super->s_inodes_count;
4944        ext2fs_dblist_dir_iterate(fs->dblist, 0, block_buf,
4945                                  search_dirent_proc, &sd);
4946}
4947
4948static void pass1d(e2fsck_t ctx, char *block_buf)
4949{
4950        ext2_filsys fs = ctx->fs;
4951        struct dup_inode        *p, *t;
4952        struct dup_block        *q;
4953        ext2_ino_t              *shared, ino;
4954        int     shared_len;
4955        int     i;
4956        int     file_ok;
4957        int     meta_data = 0;
4958        struct problem_context pctx;
4959        dnode_t *n, *m;
4960        struct block_el *s;
4961        struct inode_el *r;
4962
4963        clear_problem_context(&pctx);
4964
4965        if (!(ctx->options & E2F_OPT_PREEN))
4966                fix_problem(ctx, PR_1D_PASS_HEADER, &pctx);
4967        e2fsck_read_bitmaps(ctx);
4968
4969        pctx.num = dup_inode_count; /* dict_count(&ino_dict); */
4970        fix_problem(ctx, PR_1D_NUM_DUP_INODES, &pctx);
4971        shared = (ext2_ino_t *) e2fsck_allocate_memory(ctx,
4972                                sizeof(ext2_ino_t) * dict_count(&ino_dict),
4973                                "Shared inode list");
4974        for (n = dict_first(&ino_dict); n; n = dict_next(&ino_dict, n)) {
4975                p = (struct dup_inode *) dnode_get(n);
4976                shared_len = 0;
4977                file_ok = 1;
4978                ino = (ext2_ino_t)VOIDPTR_TO_INT(dnode_getkey(n));
4979                if (ino == EXT2_BAD_INO || ino == EXT2_RESIZE_INO)
4980                        continue;
4981
4982                /*
4983                 * Find all of the inodes which share blocks with this
4984                 * one.  First we find all of the duplicate blocks
4985                 * belonging to this inode, and then search each block
4986                 * get the list of inodes, and merge them together.
4987                 */
4988                for (s = p->block_list; s; s = s->next) {
4989                        m = dict_lookup(&blk_dict, INT_TO_VOIDPTR(s->block));
4990                        if (!m)
4991                                continue; /* Should never happen... */
4992                        q = (struct dup_block *) dnode_get(m);
4993                        if (q->num_bad > 1)
4994                                file_ok = 0;
4995                        if (check_if_fs_block(ctx, s->block)) {
4996                                file_ok = 0;
4997                                meta_data = 1;
4998                        }
4999
5000                        /*
5001                         * Add all inodes used by this block to the
5002                         * shared[] --- which is a unique list, so
5003                         * if an inode is already in shared[], don't
5004                         * add it again.
5005                         */
5006                        for (r = q->inode_list; r; r = r->next) {
5007                                if (r->inode == ino)
5008                                        continue;
5009                                for (i = 0; i < shared_len; i++)
5010                                        if (shared[i] == r->inode)
5011                                                break;
5012                                if (i == shared_len) {
5013                                        shared[shared_len++] = r->inode;
5014                                }
5015                        }
5016                }
5017
5018                /*
5019                 * Report the inode that we are working on
5020                 */
5021                pctx.inode = &p->inode;
5022                pctx.ino = ino;
5023                pctx.dir = p->dir;
5024                pctx.blkcount = p->num_dupblocks;
5025                pctx.num = meta_data ? shared_len+1 : shared_len;
5026                fix_problem(ctx, PR_1D_DUP_FILE, &pctx);
5027                pctx.blkcount = 0;
5028                pctx.num = 0;
5029
5030                if (meta_data)
5031                        fix_problem(ctx, PR_1D_SHARE_METADATA, &pctx);
5032
5033                for (i = 0; i < shared_len; i++) {
5034                        m = dict_lookup(&ino_dict, INT_TO_VOIDPTR(shared[i]));
5035                        if (!m)
5036                                continue; /* should never happen */
5037                        t = (struct dup_inode *) dnode_get(m);
5038                        /*
5039                         * Report the inode that we are sharing with
5040                         */
5041                        pctx.inode = &t->inode;
5042                        pctx.ino = shared[i];
5043                        pctx.dir = t->dir;
5044                        fix_problem(ctx, PR_1D_DUP_FILE_LIST, &pctx);
5045                }
5046                if (file_ok) {
5047                        fix_problem(ctx, PR_1D_DUP_BLOCKS_DEALT, &pctx);
5048                        continue;
5049                }
5050                if (fix_problem(ctx, PR_1D_CLONE_QUESTION, &pctx)) {
5051                        pctx.errcode = clone_file(ctx, ino, p, block_buf);
5052                        if (pctx.errcode)
5053                                fix_problem(ctx, PR_1D_CLONE_ERROR, &pctx);
5054                        else
5055                                continue;
5056                }
5057                if (fix_problem(ctx, PR_1D_DELETE_QUESTION, &pctx))
5058                        delete_file(ctx, ino, p, block_buf);
5059                else
5060                        ext2fs_unmark_valid(fs);
5061        }
5062        ext2fs_free_mem(&shared);
5063}
5064
5065/*
5066 * Drop the refcount on the dup_block structure, and clear the entry
5067 * in the block_dup_map if appropriate.
5068 */
5069static void decrement_badcount(e2fsck_t ctx, blk_t block, struct dup_block *p)
5070{
5071        p->num_bad--;
5072        if (p->num_bad <= 0 ||
5073            (p->num_bad == 1 && !check_if_fs_block(ctx, block)))
5074                ext2fs_unmark_block_bitmap(ctx->block_dup_map, block);
5075}
5076
5077static int delete_file_block(ext2_filsys fs,
5078                             blk_t      *block_nr,
5079                             e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
5080                             blk_t ref_block FSCK_ATTR((unused)),
5081                             int ref_offset FSCK_ATTR((unused)),
5082                             void *priv_data)
5083{
5084        struct process_block_struct_1b *pb;
5085        struct dup_block *p;
5086        dnode_t *n;
5087        e2fsck_t ctx;
5088
5089        pb = (struct process_block_struct_1b *) priv_data;
5090        ctx = pb->ctx;
5091
5092        if (HOLE_BLKADDR(*block_nr))
5093                return 0;
5094
5095        if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5096                n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5097                if (n) {
5098                        p = (struct dup_block *) dnode_get(n);
5099                        decrement_badcount(ctx, *block_nr, p);
5100                } else
5101                        bb_error_msg(_("internal error; can't find dup_blk for %d"),
5102                                *block_nr);
5103        } else {
5104                ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
5105                ext2fs_block_alloc_stats(fs, *block_nr, -1);
5106        }
5107
5108        return 0;
5109}
5110
5111static void delete_file(e2fsck_t ctx, ext2_ino_t ino,
5112                        struct dup_inode *dp, char* block_buf)
5113{
5114        ext2_filsys fs = ctx->fs;
5115        struct process_block_struct_1b pb;
5116        struct ext2_inode       inode;
5117        struct problem_context  pctx;
5118        unsigned int            count;
5119
5120        clear_problem_context(&pctx);
5121        pctx.ino = pb.ino = ino;
5122        pb.dup_blocks = dp->num_dupblocks;
5123        pb.ctx = ctx;
5124        pctx.str = "delete_file";
5125
5126        e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5127        if (ext2fs_inode_has_valid_blocks(&inode))
5128                pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5129                                                     delete_file_block, &pb);
5130        if (pctx.errcode)
5131                fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5132        ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
5133        ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
5134        if (ctx->inode_bad_map)
5135                ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
5136        ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
5137
5138        /* Inode may have changed by block_iterate, so reread it */
5139        e2fsck_read_inode(ctx, ino, &inode, "delete_file");
5140        inode.i_links_count = 0;
5141        inode.i_dtime = time(NULL);
5142        if (inode.i_file_acl &&
5143            (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
5144                count = 1;
5145                pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
5146                                                   block_buf, -1, &count);
5147                if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
5148                        pctx.errcode = 0;
5149                        count = 1;
5150                }
5151                if (pctx.errcode) {
5152                        pctx.blk = inode.i_file_acl;
5153                        fix_problem(ctx, PR_1B_ADJ_EA_REFCOUNT, &pctx);
5154                }
5155                /*
5156                 * If the count is zero, then arrange to have the
5157                 * block deleted.  If the block is in the block_dup_map,
5158                 * also call delete_file_block since it will take care
5159                 * of keeping the accounting straight.
5160                 */
5161                if ((count == 0) ||
5162                    ext2fs_test_block_bitmap(ctx->block_dup_map,
5163                                             inode.i_file_acl))
5164                        delete_file_block(fs, &inode.i_file_acl,
5165                                          BLOCK_COUNT_EXTATTR, 0, 0, &pb);
5166        }
5167        e2fsck_write_inode(ctx, ino, &inode, "delete_file");
5168}
5169
5170struct clone_struct {
5171        errcode_t       errcode;
5172        ext2_ino_t      dir;
5173        char    *buf;
5174        e2fsck_t ctx;
5175};
5176
5177static int clone_file_block(ext2_filsys fs,
5178                            blk_t       *block_nr,
5179                            e2_blkcnt_t blockcnt,
5180                            blk_t ref_block FSCK_ATTR((unused)),
5181                            int ref_offset FSCK_ATTR((unused)),
5182                            void *priv_data)
5183{
5184        struct dup_block *p;
5185        blk_t   new_block;
5186        errcode_t       retval;
5187        struct clone_struct *cs = (struct clone_struct *) priv_data;
5188        dnode_t *n;
5189        e2fsck_t ctx;
5190
5191        ctx = cs->ctx;
5192
5193        if (HOLE_BLKADDR(*block_nr))
5194                return 0;
5195
5196        if (ext2fs_test_block_bitmap(ctx->block_dup_map, *block_nr)) {
5197                n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(*block_nr));
5198                if (n) {
5199                        p = (struct dup_block *) dnode_get(n);
5200                        retval = ext2fs_new_block(fs, 0, ctx->block_found_map,
5201                                                  &new_block);
5202                        if (retval) {
5203                                cs->errcode = retval;
5204                                return BLOCK_ABORT;
5205                        }
5206                        if (cs->dir && (blockcnt >= 0)) {
5207                                retval = ext2fs_set_dir_block(fs->dblist,
5208                                      cs->dir, new_block, blockcnt);
5209                                if (retval) {
5210                                        cs->errcode = retval;
5211                                        return BLOCK_ABORT;
5212                                }
5213                        }
5214
5215                        retval = io_channel_read_blk(fs->io, *block_nr, 1,
5216                                                     cs->buf);
5217                        if (retval) {
5218                                cs->errcode = retval;
5219                                return BLOCK_ABORT;
5220                        }
5221                        retval = io_channel_write_blk(fs->io, new_block, 1,
5222                                                      cs->buf);
5223                        if (retval) {
5224                                cs->errcode = retval;
5225                                return BLOCK_ABORT;
5226                        }
5227                        decrement_badcount(ctx, *block_nr, p);
5228                        *block_nr = new_block;
5229                        ext2fs_mark_block_bitmap(ctx->block_found_map,
5230                                                 new_block);
5231                        ext2fs_mark_block_bitmap(fs->block_map, new_block);
5232                        return BLOCK_CHANGED;
5233                } else
5234                        bb_error_msg(_("internal error; can't find dup_blk for %d"),
5235                                *block_nr);
5236        }
5237        return 0;
5238}
5239
5240static int clone_file(e2fsck_t ctx, ext2_ino_t ino,
5241                      struct dup_inode *dp, char* block_buf)
5242{
5243        ext2_filsys fs = ctx->fs;
5244        errcode_t       retval;
5245        struct clone_struct cs;
5246        struct problem_context  pctx;
5247        blk_t           blk;
5248        dnode_t         *n;
5249        struct inode_el *ino_el;
5250        struct dup_block        *db;
5251        struct dup_inode        *di;
5252
5253        clear_problem_context(&pctx);
5254        cs.errcode = 0;
5255        cs.dir = 0;
5256        cs.ctx = ctx;
5257        retval = ext2fs_get_mem(fs->blocksize, &cs.buf);
5258        if (retval)
5259                return retval;
5260
5261        if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino))
5262                cs.dir = ino;
5263
5264        pctx.ino = ino;
5265        pctx.str = "clone_file";
5266        if (ext2fs_inode_has_valid_blocks(&dp->inode))
5267                pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
5268                                                     clone_file_block, &cs);
5269        ext2fs_mark_bb_dirty(fs);
5270        if (pctx.errcode) {
5271                fix_problem(ctx, PR_1B_BLOCK_ITERATE, &pctx);
5272                retval = pctx.errcode;
5273                goto errout;
5274        }
5275        if (cs.errcode) {
5276                bb_error_msg(_("returned from clone_file_block"));
5277                retval = cs.errcode;
5278                goto errout;
5279        }
5280        /* The inode may have changed on disk, so we have to re-read it */
5281        e2fsck_read_inode(ctx, ino, &dp->inode, "clone file EA");
5282        blk = dp->inode.i_file_acl;
5283        if (blk && (clone_file_block(fs, &dp->inode.i_file_acl,
5284                                     BLOCK_COUNT_EXTATTR, 0, 0, &cs) ==
5285                    BLOCK_CHANGED)) {
5286                e2fsck_write_inode(ctx, ino, &dp->inode, "clone file EA");
5287                /*
5288                 * If we cloned the EA block, find all other inodes
5289                 * which refered to that EA block, and modify
5290                 * them to point to the new EA block.
5291                 */
5292                n = dict_lookup(&blk_dict, INT_TO_VOIDPTR(blk));
5293                db = (struct dup_block *) dnode_get(n);
5294                for (ino_el = db->inode_list; ino_el; ino_el = ino_el->next) {
5295                        if (ino_el->inode == ino)
5296                                continue;
5297                        n = dict_lookup(&ino_dict, INT_TO_VOIDPTR(ino_el->inode));
5298                        di = (struct dup_inode *) dnode_get(n);
5299                        if (di->inode.i_file_acl == blk) {
5300                                di->inode.i_file_acl = dp->inode.i_file_acl;
5301                                e2fsck_write_inode(ctx, ino_el->inode,
5302                                           &di->inode, "clone file EA");
5303                                decrement_badcount(ctx, blk, db);
5304                        }
5305                }
5306        }
5307        retval = 0;
5308errout:
5309        ext2fs_free_mem(&cs.buf);
5310        return retval;
5311}
5312
5313/*
5314 * This routine returns 1 if a block overlaps with one of the superblocks,
5315 * group descriptors, inode bitmaps, or block bitmaps.
5316 */
5317static int check_if_fs_block(e2fsck_t ctx, blk_t test_block)
5318{
5319        ext2_filsys fs = ctx->fs;
5320        blk_t   block;
5321        dgrp_t  i;
5322
5323        block = fs->super->s_first_data_block;
5324        for (i = 0; i < fs->group_desc_count; i++) {
5325
5326                /* Check superblocks/block group descriptros */
5327                if (ext2fs_bg_has_super(fs, i)) {
5328                        if (test_block >= block &&
5329                            (test_block <= block + fs->desc_blocks))
5330                                return 1;
5331                }
5332
5333                /* Check the inode table */
5334                if ((fs->group_desc[i].bg_inode_table) &&
5335                    (test_block >= fs->group_desc[i].bg_inode_table) &&
5336                    (test_block < (fs->group_desc[i].bg_inode_table +
5337                                   fs->inode_blocks_per_group)))
5338                        return 1;
5339
5340                /* Check the bitmap blocks */
5341                if ((test_block == fs->group_desc[i].bg_block_bitmap) ||
5342                    (test_block == fs->group_desc[i].bg_inode_bitmap))
5343                        return 1;
5344
5345                block += fs->super->s_blocks_per_group;
5346        }
5347        return 0;
5348}
5349/*
5350 * pass2.c --- check directory structure
5351 *
5352 * Pass 2 of e2fsck iterates through all active directory inodes, and
5353 * applies to following tests to each directory entry in the directory
5354 * blocks in the inodes:
5355 *
5356 *      - The length of the directory entry (rec_len) should be at
5357 *              least 8 bytes, and no more than the remaining space
5358 *              left in the directory block.
5359 *      - The length of the name in the directory entry (name_len)
5360 *              should be less than (rec_len - 8).
5361 *      - The inode number in the directory entry should be within
5362 *              legal bounds.
5363 *      - The inode number should refer to a in-use inode.
5364 *      - The first entry should be '.', and its inode should be
5365 *              the inode of the directory.
5366 *      - The second entry should be '..'.
5367 *
5368 * To minimize disk seek time, the directory blocks are processed in
5369 * sorted order of block numbers.
5370 *
5371 * Pass 2 also collects the following information:
5372 *      - The inode numbers of the subdirectories for each directory.
5373 *
5374 * Pass 2 relies on the following information from previous passes:
5375 *      - The directory information collected in pass 1.
5376 *      - The inode_used_map bitmap
5377 *      - The inode_bad_map bitmap
5378 *      - The inode_dir_map bitmap
5379 *
5380 * Pass 2 frees the following data structures
5381 *      - The inode_bad_map bitmap
5382 *      - The inode_reg_map bitmap
5383 */
5384
5385/*
5386 * Keeps track of how many times an inode is referenced.
5387 */
5388static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf);
5389static int check_dir_block(ext2_filsys fs,
5390                           struct ext2_db_entry *dir_blocks_info,
5391                           void *priv_data);
5392static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *dir_blocks_info,
5393                              struct problem_context *pctx);
5394static int update_dir_block(ext2_filsys fs,
5395                            blk_t       *block_nr,
5396                            e2_blkcnt_t blockcnt,
5397                            blk_t       ref_block,
5398                            int         ref_offset,
5399                            void        *priv_data);
5400static void clear_htree(e2fsck_t ctx, ext2_ino_t ino);
5401static int htree_depth(struct dx_dir_info *dx_dir,
5402                       struct dx_dirblock_info *dx_db);
5403static int special_dir_block_cmp(const void *a, const void *b);
5404
5405struct check_dir_struct {
5406        char *buf;
5407        struct problem_context  pctx;
5408        int     count, max;
5409        e2fsck_t ctx;
5410};
5411
5412static void e2fsck_pass2(e2fsck_t ctx)
5413{
5414        struct ext2_super_block *sb = ctx->fs->super;
5415        struct problem_context  pctx;
5416        ext2_filsys             fs = ctx->fs;
5417        char                    *buf;
5418        struct dir_info         *dir;
5419        struct check_dir_struct cd;
5420        struct dx_dir_info      *dx_dir;
5421        struct dx_dirblock_info *dx_db, *dx_parent;
5422        int                     b;
5423        int                     i, depth;
5424        problem_t               code;
5425        int                     bad_dir;
5426
5427        clear_problem_context(&cd.pctx);
5428
5429        /* Pass 2 */
5430
5431        if (!(ctx->options & E2F_OPT_PREEN))
5432                fix_problem(ctx, PR_2_PASS_HEADER, &cd.pctx);
5433
5434        cd.pctx.errcode = ext2fs_create_icount2(fs, EXT2_ICOUNT_OPT_INCREMENT,
5435                                                0, ctx->inode_link_info,
5436                                                &ctx->inode_count);
5437        if (cd.pctx.errcode) {
5438                fix_problem(ctx, PR_2_ALLOCATE_ICOUNT, &cd.pctx);
5439                ctx->flags |= E2F_FLAG_ABORT;
5440                return;
5441        }
5442        buf = (char *) e2fsck_allocate_memory(ctx, 2*fs->blocksize,
5443                                              "directory scan buffer");
5444
5445        /*
5446         * Set up the parent pointer for the root directory, if
5447         * present.  (If the root directory is not present, we will
5448         * create it in pass 3.)
5449         */
5450        dir = e2fsck_get_dir_info(ctx, EXT2_ROOT_INO);
5451        if (dir)
5452                dir->parent = EXT2_ROOT_INO;
5453
5454        cd.buf = buf;
5455        cd.ctx = ctx;
5456        cd.count = 1;
5457        cd.max = ext2fs_dblist_count(fs->dblist);
5458
5459        if (ctx->progress)
5460                (void) (ctx->progress)(ctx, 2, 0, cd.max);
5461
5462        if (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX)
5463                ext2fs_dblist_sort(fs->dblist, special_dir_block_cmp);
5464
5465        cd.pctx.errcode = ext2fs_dblist_iterate(fs->dblist, check_dir_block,
5466                                                &cd);
5467        if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5468                return;
5469        if (cd.pctx.errcode) {
5470                fix_problem(ctx, PR_2_DBLIST_ITERATE, &cd.pctx);
5471                ctx->flags |= E2F_FLAG_ABORT;
5472                return;
5473        }
5474
5475#ifdef ENABLE_HTREE
5476        for (i=0; (dx_dir = e2fsck_dx_dir_info_iter(ctx, &i)) != 0;) {
5477                if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
5478                        return;
5479                if (dx_dir->numblocks == 0)
5480                        continue;
5481                clear_problem_context(&pctx);
5482                bad_dir = 0;
5483                pctx.dir = dx_dir->ino;
5484                dx_db = dx_dir->dx_block;
5485                if (dx_db->flags & DX_FLAG_REFERENCED)
5486                        dx_db->flags |= DX_FLAG_DUP_REF;
5487                else
5488                        dx_db->flags |= DX_FLAG_REFERENCED;
5489                /*
5490                 * Find all of the first and last leaf blocks, and
5491                 * update their parent's min and max hash values
5492                 */
5493                for (b=0, dx_db = dx_dir->dx_block;
5494                     b < dx_dir->numblocks;
5495                     b++, dx_db++) {
5496                        if ((dx_db->type != DX_DIRBLOCK_LEAF) ||
5497                            !(dx_db->flags & (DX_FLAG_FIRST | DX_FLAG_LAST)))
5498                                continue;
5499                        dx_parent = &dx_dir->dx_block[dx_db->parent];
5500                        /*
5501                         * XXX Make sure dx_parent->min_hash > dx_db->min_hash
5502                         */
5503                        if (dx_db->flags & DX_FLAG_FIRST)
5504                                dx_parent->min_hash = dx_db->min_hash;
5505                        /*
5506                         * XXX Make sure dx_parent->max_hash < dx_db->max_hash
5507                         */
5508                        if (dx_db->flags & DX_FLAG_LAST)
5509                                dx_parent->max_hash = dx_db->max_hash;
5510                }
5511
5512                for (b=0, dx_db = dx_dir->dx_block;
5513                     b < dx_dir->numblocks;
5514                     b++, dx_db++) {
5515                        pctx.blkcount = b;
5516                        pctx.group = dx_db->parent;
5517                        code = 0;
5518                        if (!(dx_db->flags & DX_FLAG_FIRST) &&
5519                            (dx_db->min_hash < dx_db->node_min_hash)) {
5520                                pctx.blk = dx_db->min_hash;
5521                                pctx.blk2 = dx_db->node_min_hash;
5522                                code = PR_2_HTREE_MIN_HASH;
5523                                fix_problem(ctx, code, &pctx);
5524                                bad_dir++;
5525                        }
5526                        if (dx_db->type == DX_DIRBLOCK_LEAF) {
5527                                depth = htree_depth(dx_dir, dx_db);
5528                                if (depth != dx_dir->depth) {
5529                                        code = PR_2_HTREE_BAD_DEPTH;
5530                                        fix_problem(ctx, code, &pctx);
5531                                        bad_dir++;
5532                                }
5533                        }
5534                        /*
5535                         * This test doesn't apply for the root block
5536                         * at block #0
5537                         */
5538                        if (b &&
5539                            (dx_db->max_hash > dx_db->node_max_hash)) {
5540                                pctx.blk = dx_db->max_hash;
5541                                pctx.blk2 = dx_db->node_max_hash;
5542                                code = PR_2_HTREE_MAX_HASH;
5543                                fix_problem(ctx, code, &pctx);
5544                                bad_dir++;
5545                        }
5546                        if (!(dx_db->flags & DX_FLAG_REFERENCED)) {
5547                                code = PR_2_HTREE_NOTREF;
5548                                fix_problem(ctx, code, &pctx);
5549                                bad_dir++;
5550                        } else if (dx_db->flags & DX_FLAG_DUP_REF) {
5551                                code = PR_2_HTREE_DUPREF;
5552                                fix_problem(ctx, code, &pctx);
5553                                bad_dir++;
5554                        }
5555                        if (code == 0)
5556                                continue;
5557                }
5558                if (bad_dir && fix_problem(ctx, PR_2_HTREE_CLEAR, &pctx)) {
5559                        clear_htree(ctx, dx_dir->ino);
5560                        dx_dir->numblocks = 0;
5561                }
5562        }
5563#endif
5564        ext2fs_free_mem(&buf);
5565        ext2fs_free_dblist(fs->dblist);
5566
5567        ext2fs_free_inode_bitmap(ctx->inode_bad_map);
5568        ctx->inode_bad_map = 0;
5569        ext2fs_free_inode_bitmap(ctx->inode_reg_map);
5570        ctx->inode_reg_map = 0;
5571
5572        clear_problem_context(&pctx);
5573        if (ctx->large_files) {
5574                if (!(sb->s_feature_ro_compat &
5575                      EXT2_FEATURE_RO_COMPAT_LARGE_FILE) &&
5576                    fix_problem(ctx, PR_2_FEATURE_LARGE_FILES, &pctx)) {
5577                        sb->s_feature_ro_compat |=
5578                                EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5579                        ext2fs_mark_super_dirty(fs);
5580                }
5581                if (sb->s_rev_level == EXT2_GOOD_OLD_REV &&
5582                    fix_problem(ctx, PR_1_FS_REV_LEVEL, &pctx)) {
5583                        ext2fs_update_dynamic_rev(fs);
5584                        ext2fs_mark_super_dirty(fs);
5585                }
5586        } else if (!ctx->large_files &&
5587            (sb->s_feature_ro_compat &
5588              EXT2_FEATURE_RO_COMPAT_LARGE_FILE)) {
5589                if (fs->flags & EXT2_FLAG_RW) {
5590                        sb->s_feature_ro_compat &=
5591                                ~EXT2_FEATURE_RO_COMPAT_LARGE_FILE;
5592                        ext2fs_mark_super_dirty(fs);
5593                }
5594        }
5595
5596}
5597
5598#define MAX_DEPTH 32000
5599static int htree_depth(struct dx_dir_info *dx_dir,
5600                       struct dx_dirblock_info *dx_db)
5601{
5602        int     depth = 0;
5603
5604        while (dx_db->type != DX_DIRBLOCK_ROOT && depth < MAX_DEPTH) {
5605                dx_db = &dx_dir->dx_block[dx_db->parent];
5606                depth++;
5607        }
5608        return depth;
5609}
5610
5611static int dict_de_cmp(const void *a, const void *b)
5612{
5613        const struct ext2_dir_entry *de_a, *de_b;
5614        int     a_len, b_len;
5615
5616        de_a = (const struct ext2_dir_entry *) a;
5617        a_len = de_a->name_len & 0xFF;
5618        de_b = (const struct ext2_dir_entry *) b;
5619        b_len = de_b->name_len & 0xFF;
5620
5621        if (a_len != b_len)
5622                return (a_len - b_len);
5623
5624        return strncmp(de_a->name, de_b->name, a_len);
5625}
5626
5627/*
5628 * This is special sort function that makes sure that directory blocks
5629 * with a dirblock of zero are sorted to the beginning of the list.
5630 * This guarantees that the root node of the htree directories are
5631 * processed first, so we know what hash version to use.
5632 */
5633static int special_dir_block_cmp(const void *a, const void *b)
5634{
5635        const struct ext2_db_entry *db_a =
5636                (const struct ext2_db_entry *) a;
5637        const struct ext2_db_entry *db_b =
5638                (const struct ext2_db_entry *) b;
5639
5640        if (db_a->blockcnt && !db_b->blockcnt)
5641                return 1;
5642
5643        if (!db_a->blockcnt && db_b->blockcnt)
5644                return -1;
5645
5646        if (db_a->blk != db_b->blk)
5647                return (int) (db_a->blk - db_b->blk);
5648
5649        if (db_a->ino != db_b->ino)
5650                return (int) (db_a->ino - db_b->ino);
5651
5652        return (int) (db_a->blockcnt - db_b->blockcnt);
5653}
5654
5655
5656/*
5657 * Make sure the first entry in the directory is '.', and that the
5658 * directory entry is sane.
5659 */
5660static int check_dot(e2fsck_t ctx,
5661                     struct ext2_dir_entry *dirent,
5662                     ext2_ino_t ino, struct problem_context *pctx)
5663{
5664        struct ext2_dir_entry *nextdir;
5665        int     status = 0;
5666        int     created = 0;
5667        int     new_len;
5668        int     problem = 0;
5669
5670        if (!dirent->inode)
5671                problem = PR_2_MISSING_DOT;
5672        else if (((dirent->name_len & 0xFF) != 1) ||
5673                 (dirent->name[0] != '.'))
5674                problem = PR_2_1ST_NOT_DOT;
5675        else if (dirent->name[1] != '\0')
5676                problem = PR_2_DOT_NULL_TERM;
5677
5678        if (problem) {
5679                if (fix_problem(ctx, problem, pctx)) {
5680                        if (dirent->rec_len < 12)
5681                                dirent->rec_len = 12;
5682                        dirent->inode = ino;
5683                        dirent->name_len = 1;
5684                        dirent->name[0] = '.';
5685                        dirent->name[1] = '\0';
5686                        status = 1;
5687                        created = 1;
5688                }
5689        }
5690        if (dirent->inode != ino) {
5691                if (fix_problem(ctx, PR_2_BAD_INODE_DOT, pctx)) {
5692                        dirent->inode = ino;
5693                        status = 1;
5694                }
5695        }
5696        if (dirent->rec_len > 12) {
5697                new_len = dirent->rec_len - 12;
5698                if (new_len > 12) {
5699                        if (created ||
5700                            fix_problem(ctx, PR_2_SPLIT_DOT, pctx)) {
5701                                nextdir = (struct ext2_dir_entry *)
5702                                        ((char *) dirent + 12);
5703                                dirent->rec_len = 12;
5704                                nextdir->rec_len = new_len;
5705                                nextdir->inode = 0;
5706                                nextdir->name_len = 0;
5707                                status = 1;
5708                        }
5709                }
5710        }
5711        return status;
5712}
5713
5714/*
5715 * Make sure the second entry in the directory is '..', and that the
5716 * directory entry is sane.  We do not check the inode number of '..'
5717 * here; this gets done in pass 3.
5718 */
5719static int check_dotdot(e2fsck_t ctx,
5720                        struct ext2_dir_entry *dirent,
5721                        struct dir_info *dir, struct problem_context *pctx)
5722{
5723        int             problem = 0;
5724
5725        if (!dirent->inode)
5726                problem = PR_2_MISSING_DOT_DOT;
5727        else if (((dirent->name_len & 0xFF) != 2) ||
5728                 (dirent->name[0] != '.') ||
5729                 (dirent->name[1] != '.'))
5730                problem = PR_2_2ND_NOT_DOT_DOT;
5731        else if (dirent->name[2] != '\0')
5732                problem = PR_2_DOT_DOT_NULL_TERM;
5733
5734        if (problem) {
5735                if (fix_problem(ctx, problem, pctx)) {
5736                        if (dirent->rec_len < 12)
5737                                dirent->rec_len = 12;
5738                        /*
5739                         * Note: we don't have the parent inode just
5740                         * yet, so we will fill it in with the root
5741                         * inode.  This will get fixed in pass 3.
5742                         */
5743                        dirent->inode = EXT2_ROOT_INO;
5744                        dirent->name_len = 2;
5745                        dirent->name[0] = '.';
5746                        dirent->name[1] = '.';
5747                        dirent->name[2] = '\0';
5748                        return 1;
5749                }
5750                return 0;
5751        }
5752        dir->dotdot = dirent->inode;
5753        return 0;
5754}
5755
5756/*
5757 * Check to make sure a directory entry doesn't contain any illegal
5758 * characters.
5759 */
5760static int check_name(e2fsck_t ctx,
5761                      struct ext2_dir_entry *dirent,
5762                      struct problem_context *pctx)
5763{
5764        int     i;
5765        int     fixup = -1;
5766        int     ret = 0;
5767
5768        for ( i = 0; i < (dirent->name_len & 0xFF); i++) {
5769                if (dirent->name[i] == '/' || dirent->name[i] == '\0') {
5770                        if (fixup < 0) {
5771                                fixup = fix_problem(ctx, PR_2_BAD_NAME, pctx);
5772                        }
5773                        if (fixup) {
5774                                dirent->name[i] = '.';
5775                                ret = 1;
5776                        }
5777                }
5778        }
5779        return ret;
5780}
5781
5782/*
5783 * Check the directory filetype (if present)
5784 */
5785
5786/*
5787 * Given a mode, return the ext2 file type
5788 */
5789static int ext2_file_type(unsigned int mode)
5790{
5791        if (LINUX_S_ISREG(mode))
5792                return EXT2_FT_REG_FILE;
5793
5794        if (LINUX_S_ISDIR(mode))
5795                return EXT2_FT_DIR;
5796
5797        if (LINUX_S_ISCHR(mode))
5798                return EXT2_FT_CHRDEV;
5799
5800        if (LINUX_S_ISBLK(mode))
5801                return EXT2_FT_BLKDEV;
5802
5803        if (LINUX_S_ISLNK(mode))
5804                return EXT2_FT_SYMLINK;
5805
5806        if (LINUX_S_ISFIFO(mode))
5807                return EXT2_FT_FIFO;
5808
5809        if (LINUX_S_ISSOCK(mode))
5810                return EXT2_FT_SOCK;
5811
5812        return 0;
5813}
5814
5815static int check_filetype(e2fsck_t ctx,
5816                                   struct ext2_dir_entry *dirent,
5817                                   struct problem_context *pctx)
5818{
5819        int     filetype = dirent->name_len >> 8;
5820        int     should_be = EXT2_FT_UNKNOWN;
5821        struct ext2_inode       inode;
5822
5823        if (!(ctx->fs->super->s_feature_incompat &
5824              EXT2_FEATURE_INCOMPAT_FILETYPE)) {
5825                if (filetype == 0 ||
5826                    !fix_problem(ctx, PR_2_CLEAR_FILETYPE, pctx))
5827                        return 0;
5828                dirent->name_len = dirent->name_len & 0xFF;
5829                return 1;
5830        }
5831
5832        if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dirent->inode)) {
5833                should_be = EXT2_FT_DIR;
5834        } else if (ext2fs_test_inode_bitmap(ctx->inode_reg_map,
5835                                            dirent->inode)) {
5836                should_be = EXT2_FT_REG_FILE;
5837        } else if (ctx->inode_bad_map &&
5838                   ext2fs_test_inode_bitmap(ctx->inode_bad_map,
5839                                            dirent->inode))
5840                should_be = 0;
5841        else {
5842                e2fsck_read_inode(ctx, dirent->inode, &inode,
5843                                  "check_filetype");
5844                should_be = ext2_file_type(inode.i_mode);
5845        }
5846        if (filetype == should_be)
5847                return 0;
5848        pctx->num = should_be;
5849
5850        if (fix_problem(ctx, filetype ? PR_2_BAD_FILETYPE : PR_2_SET_FILETYPE,
5851                        pctx) == 0)
5852                return 0;
5853
5854        dirent->name_len = (dirent->name_len & 0xFF) | should_be << 8;
5855        return 1;
5856}
5857
5858#ifdef ENABLE_HTREE
5859static void parse_int_node(ext2_filsys fs,
5860                           struct ext2_db_entry *db,
5861                           struct check_dir_struct *cd,
5862                           struct dx_dir_info   *dx_dir,
5863                           char *block_buf)
5864{
5865        struct          ext2_dx_root_info  *root;
5866        struct          ext2_dx_entry *ent;
5867        struct          ext2_dx_countlimit *limit;
5868        struct dx_dirblock_info *dx_db;
5869        int             i, expect_limit, count;
5870        blk_t           blk;
5871        ext2_dirhash_t  min_hash = 0xffffffff;
5872        ext2_dirhash_t  max_hash = 0;
5873        ext2_dirhash_t  hash = 0, prev_hash;
5874
5875        if (db->blockcnt == 0) {
5876                root = (struct ext2_dx_root_info *) (block_buf + 24);
5877                ent = (struct ext2_dx_entry *) (block_buf + 24 + root->info_length);
5878        } else {
5879                ent = (struct ext2_dx_entry *) (block_buf+8);
5880        }
5881        limit = (struct ext2_dx_countlimit *) ent;
5882
5883        count = ext2fs_le16_to_cpu(limit->count);
5884        expect_limit = (fs->blocksize - ((char *) ent - block_buf)) /
5885                sizeof(struct ext2_dx_entry);
5886        if (ext2fs_le16_to_cpu(limit->limit) != expect_limit) {
5887                cd->pctx.num = ext2fs_le16_to_cpu(limit->limit);
5888                if (fix_problem(cd->ctx, PR_2_HTREE_BAD_LIMIT, &cd->pctx))
5889                        goto clear_and_exit;
5890        }
5891        if (count > expect_limit) {
5892                cd->pctx.num = count;
5893                if (fix_problem(cd->ctx, PR_2_HTREE_BAD_COUNT, &cd->pctx))
5894                        goto clear_and_exit;
5895                count = expect_limit;
5896        }
5897
5898        for (i=0; i < count; i++) {
5899                prev_hash = hash;
5900                hash = i ? (ext2fs_le32_to_cpu(ent[i].hash) & ~1) : 0;
5901                blk = ext2fs_le32_to_cpu(ent[i].block) & 0x0ffffff;
5902                /* Check to make sure the block is valid */
5903                if (blk > (blk_t) dx_dir->numblocks) {
5904                        cd->pctx.blk = blk;
5905                        if (fix_problem(cd->ctx, PR_2_HTREE_BADBLK,
5906                                        &cd->pctx))
5907                                goto clear_and_exit;
5908                }
5909                if (hash < prev_hash &&
5910                    fix_problem(cd->ctx, PR_2_HTREE_HASH_ORDER, &cd->pctx))
5911                        goto clear_and_exit;
5912                dx_db = &dx_dir->dx_block[blk];
5913                if (dx_db->flags & DX_FLAG_REFERENCED) {
5914                        dx_db->flags |= DX_FLAG_DUP_REF;
5915                } else {
5916                        dx_db->flags |= DX_FLAG_REFERENCED;
5917                        dx_db->parent = db->blockcnt;
5918                }
5919                if (hash < min_hash)
5920                        min_hash = hash;
5921                if (hash > max_hash)
5922                        max_hash = hash;
5923                dx_db->node_min_hash = hash;
5924                if ((i+1) < count)
5925                        dx_db->node_max_hash =
5926                          ext2fs_le32_to_cpu(ent[i+1].hash) & ~1;
5927                else {
5928                        dx_db->node_max_hash = 0xfffffffe;
5929                        dx_db->flags |= DX_FLAG_LAST;
5930                }
5931                if (i == 0)
5932                        dx_db->flags |= DX_FLAG_FIRST;
5933        }
5934        dx_db = &dx_dir->dx_block[db->blockcnt];
5935        dx_db->min_hash = min_hash;
5936        dx_db->max_hash = max_hash;
5937        return;
5938
5939clear_and_exit:
5940        clear_htree(cd->ctx, cd->pctx.ino);
5941        dx_dir->numblocks = 0;
5942}
5943#endif /* ENABLE_HTREE */
5944
5945/*
5946 * Given a busted directory, try to salvage it somehow.
5947 *
5948 */
5949static void salvage_directory(ext2_filsys fs,
5950                              struct ext2_dir_entry *dirent,
5951                              struct ext2_dir_entry *prev,
5952                              unsigned int *offset)
5953{
5954        char    *cp = (char *) dirent;
5955        int left = fs->blocksize - *offset - dirent->rec_len;
5956        int name_len = dirent->name_len & 0xFF;
5957
5958        /*
5959         * Special case of directory entry of size 8: copy what's left
5960         * of the directory block up to cover up the invalid hole.
5961         */
5962        if ((left >= 12) && (dirent->rec_len == 8)) {
5963                memmove(cp, cp+8, left);
5964                memset(cp + left, 0, 8);
5965                return;
5966        }
5967        /*
5968         * If the directory entry overruns the end of the directory
5969         * block, and the name is small enough to fit, then adjust the
5970         * record length.
5971         */
5972        if ((left < 0) &&
5973            (name_len + 8 <= dirent->rec_len + left) &&
5974            dirent->inode <= fs->super->s_inodes_count &&
5975            strnlen(dirent->name, name_len) == name_len) {
5976                dirent->rec_len += left;
5977                return;
5978        }
5979        /*
5980         * If the directory entry is a multiple of four, so it is
5981         * valid, let the previous directory entry absorb the invalid
5982         * one.
5983         */
5984        if (prev && dirent->rec_len && (dirent->rec_len % 4) == 0) {
5985                prev->rec_len += dirent->rec_len;
5986                *offset += dirent->rec_len;
5987                return;
5988        }
5989        /*
5990         * Default salvage method --- kill all of the directory
5991         * entries for the rest of the block.  We will either try to
5992         * absorb it into the previous directory entry, or create a
5993         * new empty directory entry the rest of the directory block.
5994         */
5995        if (prev) {
5996                prev->rec_len += fs->blocksize - *offset;
5997                *offset = fs->blocksize;
5998        } else {
5999                dirent->rec_len = fs->blocksize - *offset;
6000                dirent->name_len = 0;
6001                dirent->inode = 0;
6002        }
6003}
6004
6005static int check_dir_block(ext2_filsys fs,
6006                           struct ext2_db_entry *db,
6007                           void *priv_data)
6008{
6009        struct dir_info         *subdir, *dir;
6010        struct dx_dir_info      *dx_dir;
6011#ifdef ENABLE_HTREE
6012        struct dx_dirblock_info *dx_db = 0;
6013#endif /* ENABLE_HTREE */
6014        struct ext2_dir_entry   *dirent, *prev;
6015        ext2_dirhash_t          hash;
6016        unsigned int            offset = 0;
6017        int                     dir_modified = 0;
6018        int                     dot_state;
6019        blk_t                   block_nr = db->blk;
6020        ext2_ino_t              ino = db->ino;
6021        __u16                   links;
6022        struct check_dir_struct *cd;
6023        char                    *buf;
6024        e2fsck_t                ctx;
6025        int                     problem;
6026        struct ext2_dx_root_info *root;
6027        struct ext2_dx_countlimit *limit;
6028        static dict_t de_dict;
6029        struct problem_context  pctx;
6030        int     dups_found = 0;
6031
6032        cd = (struct check_dir_struct *) priv_data;
6033        buf = cd->buf;
6034        ctx = cd->ctx;
6035
6036        if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6037                return DIRENT_ABORT;
6038
6039        if (ctx->progress && (ctx->progress)(ctx, 2, cd->count++, cd->max))
6040                return DIRENT_ABORT;
6041
6042        /*
6043         * Make sure the inode is still in use (could have been
6044         * deleted in the duplicate/bad blocks pass.
6045         */
6046        if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, ino)))
6047                return 0;
6048
6049        cd->pctx.ino = ino;
6050        cd->pctx.blk = block_nr;
6051        cd->pctx.blkcount = db->blockcnt;
6052        cd->pctx.ino2 = 0;
6053        cd->pctx.dirent = 0;
6054        cd->pctx.num = 0;
6055
6056        if (db->blk == 0) {
6057                if (allocate_dir_block(ctx, db, &cd->pctx))
6058                        return 0;
6059                block_nr = db->blk;
6060        }
6061
6062        if (db->blockcnt)
6063                dot_state = 2;
6064        else
6065                dot_state = 0;
6066
6067        if (ctx->dirs_to_hash &&
6068            ext2fs_u32_list_test(ctx->dirs_to_hash, ino))
6069                dups_found++;
6070
6071        cd->pctx.errcode = ext2fs_read_dir_block(fs, block_nr, buf);
6072        if (cd->pctx.errcode == EXT2_ET_DIR_CORRUPTED)
6073                cd->pctx.errcode = 0; /* We'll handle this ourselves */
6074        if (cd->pctx.errcode) {
6075                if (!fix_problem(ctx, PR_2_READ_DIRBLOCK, &cd->pctx)) {
6076                        ctx->flags |= E2F_FLAG_ABORT;
6077                        return DIRENT_ABORT;
6078                }
6079                memset(buf, 0, fs->blocksize);
6080        }
6081#ifdef ENABLE_HTREE
6082        dx_dir = e2fsck_get_dx_dir_info(ctx, ino);
6083        if (dx_dir && dx_dir->numblocks) {
6084                if (db->blockcnt >= dx_dir->numblocks) {
6085                        printf("XXX should never happen!!!\n");
6086                        abort();
6087                }
6088                dx_db = &dx_dir->dx_block[db->blockcnt];
6089                dx_db->type = DX_DIRBLOCK_LEAF;
6090                dx_db->phys = block_nr;
6091                dx_db->min_hash = ~0;
6092                dx_db->max_hash = 0;
6093
6094                dirent = (struct ext2_dir_entry *) buf;
6095                limit = (struct ext2_dx_countlimit *) (buf+8);
6096                if (db->blockcnt == 0) {
6097                        root = (struct ext2_dx_root_info *) (buf + 24);
6098                        dx_db->type = DX_DIRBLOCK_ROOT;
6099                        dx_db->flags |= DX_FLAG_FIRST | DX_FLAG_LAST;
6100                        if ((root->reserved_zero ||
6101                             root->info_length < 8 ||
6102                             root->indirect_levels > 1) &&
6103                            fix_problem(ctx, PR_2_HTREE_BAD_ROOT, &cd->pctx)) {
6104                                clear_htree(ctx, ino);
6105                                dx_dir->numblocks = 0;
6106                                dx_db = 0;
6107                        }
6108                        dx_dir->hashversion = root->hash_version;
6109                        dx_dir->depth = root->indirect_levels + 1;
6110                } else if ((dirent->inode == 0) &&
6111                           (dirent->rec_len == fs->blocksize) &&
6112                           (dirent->name_len == 0) &&
6113                           (ext2fs_le16_to_cpu(limit->limit) ==
6114                            ((fs->blocksize-8) /
6115                             sizeof(struct ext2_dx_entry))))
6116                        dx_db->type = DX_DIRBLOCK_NODE;
6117        }
6118#endif /* ENABLE_HTREE */
6119
6120        dict_init(&de_dict, DICTCOUNT_T_MAX, dict_de_cmp);
6121        prev = 0;
6122        do {
6123                problem = 0;
6124                dirent = (struct ext2_dir_entry *) (buf + offset);
6125                cd->pctx.dirent = dirent;
6126                cd->pctx.num = offset;
6127                if (((offset + dirent->rec_len) > fs->blocksize) ||
6128                    (dirent->rec_len < 12) ||
6129                    ((dirent->rec_len % 4) != 0) ||
6130                    (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
6131                        if (fix_problem(ctx, PR_2_DIR_CORRUPTED, &cd->pctx)) {
6132                                salvage_directory(fs, dirent, prev, &offset);
6133                                dir_modified++;
6134                                continue;
6135                        } else
6136                                goto abort_free_dict;
6137                }
6138                if ((dirent->name_len & 0xFF) > EXT2_NAME_LEN) {
6139                        if (fix_problem(ctx, PR_2_FILENAME_LONG, &cd->pctx)) {
6140                                dirent->name_len = EXT2_NAME_LEN;
6141                                dir_modified++;
6142                        }
6143                }
6144
6145                if (dot_state == 0) {
6146                        if (check_dot(ctx, dirent, ino, &cd->pctx))
6147                                dir_modified++;
6148                } else if (dot_state == 1) {
6149                        dir = e2fsck_get_dir_info(ctx, ino);
6150                        if (!dir) {
6151                                fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6152                                goto abort_free_dict;
6153                        }
6154                        if (check_dotdot(ctx, dirent, dir, &cd->pctx))
6155                                dir_modified++;
6156                } else if (dirent->inode == ino) {
6157                        problem = PR_2_LINK_DOT;
6158                        if (fix_problem(ctx, PR_2_LINK_DOT, &cd->pctx)) {
6159                                dirent->inode = 0;
6160                                dir_modified++;
6161                                goto next;
6162                        }
6163                }
6164                if (!dirent->inode)
6165                        goto next;
6166
6167                /*
6168                 * Make sure the inode listed is a legal one.
6169                 */
6170                if (((dirent->inode != EXT2_ROOT_INO) &&
6171                     (dirent->inode < EXT2_FIRST_INODE(fs->super))) ||
6172                    (dirent->inode > fs->super->s_inodes_count)) {
6173                        problem = PR_2_BAD_INO;
6174                } else if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map,
6175                                               dirent->inode))) {
6176                        /*
6177                         * If the inode is unused, offer to clear it.
6178                         */
6179                        problem = PR_2_UNUSED_INODE;
6180                } else if ((dot_state > 1) &&
6181                           ((dirent->name_len & 0xFF) == 1) &&
6182                           (dirent->name[0] == '.')) {
6183                        /*
6184                         * If there's a '.' entry in anything other
6185                         * than the first directory entry, it's a
6186                         * duplicate entry that should be removed.
6187                         */
6188                        problem = PR_2_DUP_DOT;
6189                } else if ((dot_state > 1) &&
6190                           ((dirent->name_len & 0xFF) == 2) &&
6191                           (dirent->name[0] == '.') &&
6192                           (dirent->name[1] == '.')) {
6193                        /*
6194                         * If there's a '..' entry in anything other
6195                         * than the second directory entry, it's a
6196                         * duplicate entry that should be removed.
6197                         */
6198                        problem = PR_2_DUP_DOT_DOT;
6199                } else if ((dot_state > 1) &&
6200                           (dirent->inode == EXT2_ROOT_INO)) {
6201                        /*
6202                         * Don't allow links to the root directory.
6203                         * We check this specially to make sure we
6204                         * catch this error case even if the root
6205                         * directory hasn't been created yet.
6206                         */
6207                        problem = PR_2_LINK_ROOT;
6208                } else if ((dot_state > 1) &&
6209                           (dirent->name_len & 0xFF) == 0) {
6210                        /*
6211                         * Don't allow zero-length directory names.
6212                         */
6213                        problem = PR_2_NULL_NAME;
6214                }
6215
6216                if (problem) {
6217                        if (fix_problem(ctx, problem, &cd->pctx)) {
6218                                dirent->inode = 0;
6219                                dir_modified++;
6220                                goto next;
6221                        } else {
6222                                ext2fs_unmark_valid(fs);
6223                                if (problem == PR_2_BAD_INO)
6224                                        goto next;
6225                        }
6226                }
6227
6228                /*
6229                 * If the inode was marked as having bad fields in
6230                 * pass1, process it and offer to fix/clear it.
6231                 * (We wait until now so that we can display the
6232                 * pathname to the user.)
6233                 */
6234                if (ctx->inode_bad_map &&
6235                    ext2fs_test_inode_bitmap(ctx->inode_bad_map,
6236                                             dirent->inode)) {
6237                        if (e2fsck_process_bad_inode(ctx, ino,
6238                                                     dirent->inode,
6239                                                     buf + fs->blocksize)) {
6240                                dirent->inode = 0;
6241                                dir_modified++;
6242                                goto next;
6243                        }
6244                        if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6245                                return DIRENT_ABORT;
6246                }
6247
6248                if (check_name(ctx, dirent, &cd->pctx))
6249                        dir_modified++;
6250
6251                if (check_filetype(ctx, dirent, &cd->pctx))
6252                        dir_modified++;
6253
6254#ifdef ENABLE_HTREE
6255                if (dx_db) {
6256                        ext2fs_dirhash(dx_dir->hashversion, dirent->name,
6257                                       (dirent->name_len & 0xFF),
6258                                       fs->super->s_hash_seed, &hash, 0);
6259                        if (hash < dx_db->min_hash)
6260                                dx_db->min_hash = hash;
6261                        if (hash > dx_db->max_hash)
6262                                dx_db->max_hash = hash;
6263                }
6264#endif
6265
6266                /*
6267                 * If this is a directory, then mark its parent in its
6268                 * dir_info structure.  If the parent field is already
6269                 * filled in, then this directory has more than one
6270                 * hard link.  We assume the first link is correct,
6271                 * and ask the user if he/she wants to clear this one.
6272                 */
6273                if ((dot_state > 1) &&
6274                    (ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6275                                              dirent->inode))) {
6276                        subdir = e2fsck_get_dir_info(ctx, dirent->inode);
6277                        if (!subdir) {
6278                                cd->pctx.ino = dirent->inode;
6279                                fix_problem(ctx, PR_2_NO_DIRINFO, &cd->pctx);
6280                                goto abort_free_dict;
6281                        }
6282                        if (subdir->parent) {
6283                                cd->pctx.ino2 = subdir->parent;
6284                                if (fix_problem(ctx, PR_2_LINK_DIR,
6285                                                &cd->pctx)) {
6286                                        dirent->inode = 0;
6287                                        dir_modified++;
6288                                        goto next;
6289                                }
6290                                cd->pctx.ino2 = 0;
6291                        } else
6292                                subdir->parent = ino;
6293                }
6294
6295                if (dups_found) {
6296                        ;
6297                } else if (dict_lookup(&de_dict, dirent)) {
6298                        clear_problem_context(&pctx);
6299                        pctx.ino = ino;
6300                        pctx.dirent = dirent;
6301                        fix_problem(ctx, PR_2_REPORT_DUP_DIRENT, &pctx);
6302                        if (!ctx->dirs_to_hash)
6303                                ext2fs_u32_list_create(&ctx->dirs_to_hash, 50);
6304                        if (ctx->dirs_to_hash)
6305                                ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6306                        dups_found++;
6307                } else
6308                        dict_alloc_insert(&de_dict, dirent, dirent);
6309
6310                ext2fs_icount_increment(ctx->inode_count, dirent->inode,
6311                                        &links);
6312                if (links > 1)
6313                        ctx->fs_links_count++;
6314                ctx->fs_total_count++;
6315        next:
6316                prev = dirent;
6317                offset += dirent->rec_len;
6318                dot_state++;
6319        } while (offset < fs->blocksize);
6320#ifdef ENABLE_HTREE
6321        if (dx_db) {
6322                cd->pctx.dir = cd->pctx.ino;
6323                if ((dx_db->type == DX_DIRBLOCK_ROOT) ||
6324                    (dx_db->type == DX_DIRBLOCK_NODE))
6325                        parse_int_node(fs, db, cd, dx_dir, buf);
6326        }
6327#endif /* ENABLE_HTREE */
6328        if (offset != fs->blocksize) {
6329                cd->pctx.num = dirent->rec_len - fs->blocksize + offset;
6330                if (fix_problem(ctx, PR_2_FINAL_RECLEN, &cd->pctx)) {
6331                        dirent->rec_len = cd->pctx.num;
6332                        dir_modified++;
6333                }
6334        }
6335        if (dir_modified) {
6336                cd->pctx.errcode = ext2fs_write_dir_block(fs, block_nr, buf);
6337                if (cd->pctx.errcode) {
6338                        if (!fix_problem(ctx, PR_2_WRITE_DIRBLOCK,
6339                                         &cd->pctx))
6340                                goto abort_free_dict;
6341                }
6342                ext2fs_mark_changed(fs);
6343        }
6344        dict_free_nodes(&de_dict);
6345        return 0;
6346abort_free_dict:
6347        dict_free_nodes(&de_dict);
6348        ctx->flags |= E2F_FLAG_ABORT;
6349        return DIRENT_ABORT;
6350}
6351
6352/*
6353 * This function is called to deallocate a block, and is an interator
6354 * functioned called by deallocate inode via ext2fs_iterate_block().
6355 */
6356static int deallocate_inode_block(ext2_filsys fs, blk_t *block_nr,
6357                                  e2_blkcnt_t blockcnt FSCK_ATTR((unused)),
6358                                  blk_t ref_block FSCK_ATTR((unused)),
6359                                  int ref_offset FSCK_ATTR((unused)),
6360                                  void *priv_data)
6361{
6362        e2fsck_t        ctx = (e2fsck_t) priv_data;
6363
6364        if (HOLE_BLKADDR(*block_nr))
6365                return 0;
6366        if ((*block_nr < fs->super->s_first_data_block) ||
6367            (*block_nr >= fs->super->s_blocks_count))
6368                return 0;
6369        ext2fs_unmark_block_bitmap(ctx->block_found_map, *block_nr);
6370        ext2fs_block_alloc_stats(fs, *block_nr, -1);
6371        return 0;
6372}
6373
6374/*
6375 * This fuction deallocates an inode
6376 */
6377static void deallocate_inode(e2fsck_t ctx, ext2_ino_t ino, char* block_buf)
6378{
6379        ext2_filsys fs = ctx->fs;
6380        struct ext2_inode       inode;
6381        struct problem_context  pctx;
6382        __u32                   count;
6383
6384        ext2fs_icount_store(ctx->inode_link_info, ino, 0);
6385        e2fsck_read_inode(ctx, ino, &inode, "deallocate_inode");
6386        inode.i_links_count = 0;
6387        inode.i_dtime = time(NULL);
6388        e2fsck_write_inode(ctx, ino, &inode, "deallocate_inode");
6389        clear_problem_context(&pctx);
6390        pctx.ino = ino;
6391
6392        /*
6393         * Fix up the bitmaps...
6394         */
6395        e2fsck_read_bitmaps(ctx);
6396        ext2fs_unmark_inode_bitmap(ctx->inode_used_map, ino);
6397        ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, ino);
6398        if (ctx->inode_bad_map)
6399                ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6400        ext2fs_inode_alloc_stats2(fs, ino, -1, LINUX_S_ISDIR(inode.i_mode));
6401
6402        if (inode.i_file_acl &&
6403            (fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR)) {
6404                pctx.errcode = ext2fs_adjust_ea_refcount(fs, inode.i_file_acl,
6405                                                   block_buf, -1, &count);
6406                if (pctx.errcode == EXT2_ET_BAD_EA_BLOCK_NUM) {
6407                        pctx.errcode = 0;
6408                        count = 1;
6409                }
6410                if (pctx.errcode) {
6411                        pctx.blk = inode.i_file_acl;
6412                        fix_problem(ctx, PR_2_ADJ_EA_REFCOUNT, &pctx);
6413                        ctx->flags |= E2F_FLAG_ABORT;
6414                        return;
6415                }
6416                if (count == 0) {
6417                        ext2fs_unmark_block_bitmap(ctx->block_found_map,
6418                                                   inode.i_file_acl);
6419                        ext2fs_block_alloc_stats(fs, inode.i_file_acl, -1);
6420                }
6421                inode.i_file_acl = 0;
6422        }
6423
6424        if (!ext2fs_inode_has_valid_blocks(&inode))
6425                return;
6426
6427        if (LINUX_S_ISREG(inode.i_mode) &&
6428            (inode.i_size_high || inode.i_size & 0x80000000UL))
6429                ctx->large_files--;
6430
6431        pctx.errcode = ext2fs_block_iterate2(fs, ino, 0, block_buf,
6432                                            deallocate_inode_block, ctx);
6433        if (pctx.errcode) {
6434                fix_problem(ctx, PR_2_DEALLOC_INODE, &pctx);
6435                ctx->flags |= E2F_FLAG_ABORT;
6436                return;
6437        }
6438}
6439
6440/*
6441 * This fuction clears the htree flag on an inode
6442 */
6443static void clear_htree(e2fsck_t ctx, ext2_ino_t ino)
6444{
6445        struct ext2_inode       inode;
6446
6447        e2fsck_read_inode(ctx, ino, &inode, "clear_htree");
6448        inode.i_flags = inode.i_flags & ~EXT2_INDEX_FL;
6449        e2fsck_write_inode(ctx, ino, &inode, "clear_htree");
6450        if (ctx->dirs_to_hash)
6451                ext2fs_u32_list_add(ctx->dirs_to_hash, ino);
6452}
6453
6454
6455static int e2fsck_process_bad_inode(e2fsck_t ctx, ext2_ino_t dir,
6456                                    ext2_ino_t ino, char *buf)
6457{
6458        ext2_filsys fs = ctx->fs;
6459        struct ext2_inode       inode;
6460        int                     inode_modified = 0;
6461        int                     not_fixed = 0;
6462        unsigned char           *frag, *fsize;
6463        struct problem_context  pctx;
6464        int     problem = 0;
6465
6466        e2fsck_read_inode(ctx, ino, &inode, "process_bad_inode");
6467
6468        clear_problem_context(&pctx);
6469        pctx.ino = ino;
6470        pctx.dir = dir;
6471        pctx.inode = &inode;
6472
6473        if (inode.i_file_acl &&
6474            !(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_EXT_ATTR) &&
6475            fix_problem(ctx, PR_2_FILE_ACL_ZERO, &pctx)) {
6476                inode.i_file_acl = 0;
6477#if BB_BIG_ENDIAN
6478                /*
6479                 * This is a special kludge to deal with long symlinks
6480                 * on big endian systems.  i_blocks had already been
6481                 * decremented earlier in pass 1, but since i_file_acl
6482                 * hadn't yet been cleared, ext2fs_read_inode()
6483                 * assumed that the file was short symlink and would
6484                 * not have byte swapped i_block[0].  Hence, we have
6485                 * to byte-swap it here.
6486                 */
6487                if (LINUX_S_ISLNK(inode.i_mode) &&
6488                    (fs->flags & EXT2_FLAG_SWAP_BYTES) &&
6489                    (inode.i_blocks == fs->blocksize >> 9))
6490                        inode.i_block[0] = ext2fs_swab32(inode.i_block[0]);
6491#endif
6492                inode_modified++;
6493        } else
6494                not_fixed++;
6495
6496        if (!LINUX_S_ISDIR(inode.i_mode) && !LINUX_S_ISREG(inode.i_mode) &&
6497            !LINUX_S_ISCHR(inode.i_mode) && !LINUX_S_ISBLK(inode.i_mode) &&
6498            !LINUX_S_ISLNK(inode.i_mode) && !LINUX_S_ISFIFO(inode.i_mode) &&
6499            !(LINUX_S_ISSOCK(inode.i_mode)))
6500                problem = PR_2_BAD_MODE;
6501        else if (LINUX_S_ISCHR(inode.i_mode)
6502                 && !e2fsck_pass1_check_device_inode(fs, &inode))
6503                problem = PR_2_BAD_CHAR_DEV;
6504        else if (LINUX_S_ISBLK(inode.i_mode)
6505                 && !e2fsck_pass1_check_device_inode(fs, &inode))
6506                problem = PR_2_BAD_BLOCK_DEV;
6507        else if (LINUX_S_ISFIFO(inode.i_mode)
6508                 && !e2fsck_pass1_check_device_inode(fs, &inode))
6509                problem = PR_2_BAD_FIFO;
6510        else if (LINUX_S_ISSOCK(inode.i_mode)
6511                 && !e2fsck_pass1_check_device_inode(fs, &inode))
6512                problem = PR_2_BAD_SOCKET;
6513        else if (LINUX_S_ISLNK(inode.i_mode)
6514                 && !e2fsck_pass1_check_symlink(fs, &inode, buf)) {
6515                problem = PR_2_INVALID_SYMLINK;
6516        }
6517
6518        if (problem) {
6519                if (fix_problem(ctx, problem, &pctx)) {
6520                        deallocate_inode(ctx, ino, 0);
6521                        if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6522                                return 0;
6523                        return 1;
6524                } else
6525                        not_fixed++;
6526                problem = 0;
6527        }
6528
6529        if (inode.i_faddr) {
6530                if (fix_problem(ctx, PR_2_FADDR_ZERO, &pctx)) {
6531                        inode.i_faddr = 0;
6532                        inode_modified++;
6533                } else
6534                        not_fixed++;
6535        }
6536
6537        switch (fs->super->s_creator_os) {
6538            case EXT2_OS_LINUX:
6539                frag = &inode.osd2.linux2.l_i_frag;
6540                fsize = &inode.osd2.linux2.l_i_fsize;
6541                break;
6542            case EXT2_OS_HURD:
6543                frag = &inode.osd2.hurd2.h_i_frag;
6544                fsize = &inode.osd2.hurd2.h_i_fsize;
6545                break;
6546            case EXT2_OS_MASIX:
6547                frag = &inode.osd2.masix2.m_i_frag;
6548                fsize = &inode.osd2.masix2.m_i_fsize;
6549                break;
6550            default:
6551                frag = fsize = 0;
6552        }
6553        if (frag && *frag) {
6554                pctx.num = *frag;
6555                if (fix_problem(ctx, PR_2_FRAG_ZERO, &pctx)) {
6556                        *frag = 0;
6557                        inode_modified++;
6558                } else
6559                        not_fixed++;
6560                pctx.num = 0;
6561        }
6562        if (fsize && *fsize) {
6563                pctx.num = *fsize;
6564                if (fix_problem(ctx, PR_2_FSIZE_ZERO, &pctx)) {
6565                        *fsize = 0;
6566                        inode_modified++;
6567                } else
6568                        not_fixed++;
6569                pctx.num = 0;
6570        }
6571
6572        if (inode.i_file_acl &&
6573            ((inode.i_file_acl < fs->super->s_first_data_block) ||
6574             (inode.i_file_acl >= fs->super->s_blocks_count))) {
6575                if (fix_problem(ctx, PR_2_FILE_ACL_BAD, &pctx)) {
6576                        inode.i_file_acl = 0;
6577                        inode_modified++;
6578                } else
6579                        not_fixed++;
6580        }
6581        if (inode.i_dir_acl &&
6582            LINUX_S_ISDIR(inode.i_mode)) {
6583                if (fix_problem(ctx, PR_2_DIR_ACL_ZERO, &pctx)) {
6584                        inode.i_dir_acl = 0;
6585                        inode_modified++;
6586                } else
6587                        not_fixed++;
6588        }
6589
6590        if (inode_modified)
6591                e2fsck_write_inode(ctx, ino, &inode, "process_bad_inode");
6592        if (!not_fixed)
6593                ext2fs_unmark_inode_bitmap(ctx->inode_bad_map, ino);
6594        return 0;
6595}
6596
6597
6598/*
6599 * allocate_dir_block --- this function allocates a new directory
6600 *      block for a particular inode; this is done if a directory has
6601 *      a "hole" in it, or if a directory has a illegal block number
6602 *      that was zeroed out and now needs to be replaced.
6603 */
6604static int allocate_dir_block(e2fsck_t ctx, struct ext2_db_entry *db,
6605                              struct problem_context *pctx)
6606{
6607        ext2_filsys fs = ctx->fs;
6608        blk_t                   blk;
6609        char                    *block;
6610        struct ext2_inode       inode;
6611
6612        if (fix_problem(ctx, PR_2_DIRECTORY_HOLE, pctx) == 0)
6613                return 1;
6614
6615        /*
6616         * Read the inode and block bitmaps in; we'll be messing with
6617         * them.
6618         */
6619        e2fsck_read_bitmaps(ctx);
6620
6621        /*
6622         * First, find a free block
6623         */
6624        pctx->errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6625        if (pctx->errcode) {
6626                pctx->str = "ext2fs_new_block";
6627                fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6628                return 1;
6629        }
6630        ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6631        ext2fs_mark_block_bitmap(fs->block_map, blk);
6632        ext2fs_mark_bb_dirty(fs);
6633
6634        /*
6635         * Now let's create the actual data block for the inode
6636         */
6637        if (db->blockcnt)
6638                pctx->errcode = ext2fs_new_dir_block(fs, 0, 0, &block);
6639        else
6640                pctx->errcode = ext2fs_new_dir_block(fs, db->ino,
6641                                                     EXT2_ROOT_INO, &block);
6642
6643        if (pctx->errcode) {
6644                pctx->str = "ext2fs_new_dir_block";
6645                fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6646                return 1;
6647        }
6648
6649        pctx->errcode = ext2fs_write_dir_block(fs, blk, block);
6650        ext2fs_free_mem(&block);
6651        if (pctx->errcode) {
6652                pctx->str = "ext2fs_write_dir_block";
6653                fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6654                return 1;
6655        }
6656
6657        /*
6658         * Update the inode block count
6659         */
6660        e2fsck_read_inode(ctx, db->ino, &inode, "allocate_dir_block");
6661        inode.i_blocks += fs->blocksize / 512;
6662        if (inode.i_size < (db->blockcnt+1) * fs->blocksize)
6663                inode.i_size = (db->blockcnt+1) * fs->blocksize;
6664        e2fsck_write_inode(ctx, db->ino, &inode, "allocate_dir_block");
6665
6666        /*
6667         * Finally, update the block pointers for the inode
6668         */
6669        db->blk = blk;
6670        pctx->errcode = ext2fs_block_iterate2(fs, db->ino, BLOCK_FLAG_HOLE,
6671                                      0, update_dir_block, db);
6672        if (pctx->errcode) {
6673                pctx->str = "ext2fs_block_iterate";
6674                fix_problem(ctx, PR_2_ALLOC_DIRBOCK, pctx);
6675                return 1;
6676        }
6677
6678        return 0;
6679}
6680
6681/*
6682 * This is a helper function for allocate_dir_block().
6683 */
6684static int update_dir_block(ext2_filsys fs FSCK_ATTR((unused)),
6685                            blk_t       *block_nr,
6686                            e2_blkcnt_t blockcnt,
6687                            blk_t ref_block FSCK_ATTR((unused)),
6688                            int ref_offset FSCK_ATTR((unused)),
6689                            void *priv_data)
6690{
6691        struct ext2_db_entry *db;
6692
6693        db = (struct ext2_db_entry *) priv_data;
6694        if (db->blockcnt == (int) blockcnt) {
6695                *block_nr = db->blk;
6696                return BLOCK_CHANGED;
6697        }
6698        return 0;
6699}
6700
6701/*
6702 * pass3.c -- pass #3 of e2fsck: Check for directory connectivity
6703 *
6704 * Pass #3 assures that all directories are connected to the
6705 * filesystem tree, using the following algorithm:
6706 *
6707 * First, the root directory is checked to make sure it exists; if
6708 * not, e2fsck will offer to create a new one.  It is then marked as
6709 * "done".
6710 *
6711 * Then, pass3 interates over all directory inodes; for each directory
6712 * it attempts to trace up the filesystem tree, using dirinfo.parent
6713 * until it reaches a directory which has been marked "done".  If it
6714 * cannot do so, then the directory must be disconnected, and e2fsck
6715 * will offer to reconnect it to /lost+found.  While it is chasing
6716 * parent pointers up the filesystem tree, if pass3 sees a directory
6717 * twice, then it has detected a filesystem loop, and it will again
6718 * offer to reconnect the directory to /lost+found in to break the
6719 * filesystem loop.
6720 *
6721 * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to
6722 * reconnect inodes to /lost+found; this subroutine is also used by
6723 * pass 4.  e2fsck_reconnect_file() calls get_lost_and_found(), which
6724 * is responsible for creating /lost+found if it does not exist.
6725 *
6726 * Pass 3 frees the following data structures:
6727 *      - The dirinfo directory information cache.
6728 */
6729
6730static void check_root(e2fsck_t ctx);
6731static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6732                           struct problem_context *pctx);
6733static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent);
6734
6735static ext2fs_inode_bitmap inode_loop_detect;
6736static ext2fs_inode_bitmap inode_done_map;
6737
6738static void e2fsck_pass3(e2fsck_t ctx)
6739{
6740        ext2_filsys fs = ctx->fs;
6741        int             i;
6742        struct problem_context  pctx;
6743        struct dir_info *dir;
6744        unsigned long maxdirs, count;
6745
6746        clear_problem_context(&pctx);
6747
6748        /* Pass 3 */
6749
6750        if (!(ctx->options & E2F_OPT_PREEN))
6751                fix_problem(ctx, PR_3_PASS_HEADER, &pctx);
6752
6753        /*
6754         * Allocate some bitmaps to do loop detection.
6755         */
6756        pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"),
6757                                                    &inode_done_map);
6758        if (pctx.errcode) {
6759                pctx.num = 2;
6760                fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx);
6761                ctx->flags |= E2F_FLAG_ABORT;
6762                goto abort_exit;
6763        }
6764        check_root(ctx);
6765        if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6766                goto abort_exit;
6767
6768        ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO);
6769
6770        maxdirs = e2fsck_get_num_dirinfo(ctx);
6771        count = 1;
6772
6773        if (ctx->progress)
6774                if ((ctx->progress)(ctx, 3, 0, maxdirs))
6775                        goto abort_exit;
6776
6777        for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) {
6778                if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
6779                        goto abort_exit;
6780                if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs))
6781                        goto abort_exit;
6782                if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino))
6783                        if (check_directory(ctx, dir, &pctx))
6784                                goto abort_exit;
6785        }
6786
6787        /*
6788         * Force the creation of /lost+found if not present
6789         */
6790        if ((ctx->flags & E2F_OPT_READONLY) == 0)
6791                e2fsck_get_lost_and_found(ctx, 1);
6792
6793        /*
6794         * If there are any directories that need to be indexed or
6795         * optimized, do it here.
6796         */
6797        e2fsck_rehash_directories(ctx);
6798
6799abort_exit:
6800        e2fsck_free_dir_info(ctx);
6801        ext2fs_free_inode_bitmap(inode_loop_detect);
6802        inode_loop_detect = 0;
6803        ext2fs_free_inode_bitmap(inode_done_map);
6804        inode_done_map = 0;
6805}
6806
6807/*
6808 * This makes sure the root inode is present; if not, we ask if the
6809 * user wants us to create it.  Not creating it is a fatal error.
6810 */
6811static void check_root(e2fsck_t ctx)
6812{
6813        ext2_filsys fs = ctx->fs;
6814        blk_t                   blk;
6815        struct ext2_inode       inode;
6816        char *                  block;
6817        struct problem_context  pctx;
6818
6819        clear_problem_context(&pctx);
6820
6821        if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) {
6822                /*
6823                 * If the root inode is not a directory, die here.  The
6824                 * user must have answered 'no' in pass1 when we
6825                 * offered to clear it.
6826                 */
6827                if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map,
6828                                               EXT2_ROOT_INO))) {
6829                        fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx);
6830                        ctx->flags |= E2F_FLAG_ABORT;
6831                }
6832                return;
6833        }
6834
6835        if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) {
6836                fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx);
6837                ctx->flags |= E2F_FLAG_ABORT;
6838                return;
6839        }
6840
6841        e2fsck_read_bitmaps(ctx);
6842
6843        /*
6844         * First, find a free block
6845         */
6846        pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
6847        if (pctx.errcode) {
6848                pctx.str = "ext2fs_new_block";
6849                fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6850                ctx->flags |= E2F_FLAG_ABORT;
6851                return;
6852        }
6853        ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
6854        ext2fs_mark_block_bitmap(fs->block_map, blk);
6855        ext2fs_mark_bb_dirty(fs);
6856
6857        /*
6858         * Now let's create the actual data block for the inode
6859         */
6860        pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO,
6861                                            &block);
6862        if (pctx.errcode) {
6863                pctx.str = "ext2fs_new_dir_block";
6864                fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6865                ctx->flags |= E2F_FLAG_ABORT;
6866                return;
6867        }
6868
6869        pctx.errcode = ext2fs_write_dir_block(fs, blk, block);
6870        if (pctx.errcode) {
6871                pctx.str = "ext2fs_write_dir_block";
6872                fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6873                ctx->flags |= E2F_FLAG_ABORT;
6874                return;
6875        }
6876        ext2fs_free_mem(&block);
6877
6878        /*
6879         * Set up the inode structure
6880         */
6881        memset(&inode, 0, sizeof(inode));
6882        inode.i_mode = 040755;
6883        inode.i_size = fs->blocksize;
6884        inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
6885        inode.i_links_count = 2;
6886        inode.i_blocks = fs->blocksize / 512;
6887        inode.i_block[0] = blk;
6888
6889        /*
6890         * Write out the inode.
6891         */
6892        pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
6893        if (pctx.errcode) {
6894                pctx.str = "ext2fs_write_inode";
6895                fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx);
6896                ctx->flags |= E2F_FLAG_ABORT;
6897                return;
6898        }
6899
6900        /*
6901         * Miscellaneous bookkeeping...
6902         */
6903        e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO);
6904        ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2);
6905        ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2);
6906
6907        ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO);
6908        ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO);
6909        ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO);
6910        ext2fs_mark_ib_dirty(fs);
6911}
6912
6913/*
6914 * This subroutine is responsible for making sure that a particular
6915 * directory is connected to the root; if it isn't we trace it up as
6916 * far as we can go, and then offer to connect the resulting parent to
6917 * the lost+found.  We have to do loop detection; if we ever discover
6918 * a loop, we treat that as a disconnected directory and offer to
6919 * reparent it to lost+found.
6920 *
6921 * However, loop detection is expensive, because for very large
6922 * filesystems, the inode_loop_detect bitmap is huge, and clearing it
6923 * is non-trivial.  Loops in filesystems are also a rare error case,
6924 * and we shouldn't optimize for error cases.  So we try two passes of
6925 * the algorithm.  The first time, we ignore loop detection and merely
6926 * increment a counter; if the counter exceeds some extreme threshold,
6927 * then we try again with the loop detection bitmap enabled.
6928 */
6929static int check_directory(e2fsck_t ctx, struct dir_info *dir,
6930                           struct problem_context *pctx)
6931{
6932        ext2_filsys     fs = ctx->fs;
6933        struct dir_info *p = dir;
6934        int             loop_pass = 0, parent_count = 0;
6935
6936        if (!p)
6937                return 0;
6938
6939        while (1) {
6940                /*
6941                 * Mark this inode as being "done"; by the time we
6942                 * return from this function, the inode we either be
6943                 * verified as being connected to the directory tree,
6944                 * or we will have offered to reconnect this to
6945                 * lost+found.
6946                 *
6947                 * If it was marked done already, then we've reached a
6948                 * parent we've already checked.
6949                 */
6950                if (ext2fs_mark_inode_bitmap(inode_done_map, p->ino))
6951                        break;
6952
6953                /*
6954                 * If this directory doesn't have a parent, or we've
6955                 * seen the parent once already, then offer to
6956                 * reparent it to lost+found
6957                 */
6958                if (!p->parent ||
6959                    (loop_pass &&
6960                     (ext2fs_test_inode_bitmap(inode_loop_detect,
6961                                              p->parent)))) {
6962                        pctx->ino = p->ino;
6963                        if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) {
6964                                if (e2fsck_reconnect_file(ctx, pctx->ino))
6965                                        ext2fs_unmark_valid(fs);
6966                                else {
6967                                        p = e2fsck_get_dir_info(ctx, pctx->ino);
6968                                        p->parent = ctx->lost_and_found;
6969                                        fix_dotdot(ctx, p, ctx->lost_and_found);
6970                                }
6971                        }
6972                        break;
6973                }
6974                p = e2fsck_get_dir_info(ctx, p->parent);
6975                if (!p) {
6976                        fix_problem(ctx, PR_3_NO_DIRINFO, pctx);
6977                        return 0;
6978                }
6979                if (loop_pass) {
6980                        ext2fs_mark_inode_bitmap(inode_loop_detect,
6981                                                 p->ino);
6982                } else if (parent_count++ > 2048) {
6983                        /*
6984                         * If we've run into a path depth that's
6985                         * greater than 2048, try again with the inode
6986                         * loop bitmap turned on and start from the
6987                         * top.
6988                         */
6989                        loop_pass = 1;
6990                        if (inode_loop_detect)
6991                                ext2fs_clear_inode_bitmap(inode_loop_detect);
6992                        else {
6993                                pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect);
6994                                if (pctx->errcode) {
6995                                        pctx->num = 1;
6996                                        fix_problem(ctx,
6997                                    PR_3_ALLOCATE_IBITMAP_ERROR, pctx);
6998                                        ctx->flags |= E2F_FLAG_ABORT;
6999                                        return -1;
7000                                }
7001                        }
7002                        p = dir;
7003                }
7004        }
7005
7006        /*
7007         * Make sure that .. and the parent directory are the same;
7008         * offer to fix it if not.
7009         */
7010        if (dir->parent != dir->dotdot) {
7011                pctx->ino = dir->ino;
7012                pctx->ino2 = dir->dotdot;
7013                pctx->dir = dir->parent;
7014                if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx))
7015                        fix_dotdot(ctx, dir, dir->parent);
7016        }
7017        return 0;
7018}
7019
7020/*
7021 * This routine gets the lost_and_found inode, making it a directory
7022 * if necessary
7023 */
7024ext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix)
7025{
7026        ext2_filsys fs = ctx->fs;
7027        ext2_ino_t                      ino;
7028        blk_t                   blk;
7029        errcode_t               retval;
7030        struct ext2_inode       inode;
7031        char *                  block;
7032        static const char       name[] = "lost+found";
7033        struct  problem_context pctx;
7034        struct dir_info         *dirinfo;
7035
7036        if (ctx->lost_and_found)
7037                return ctx->lost_and_found;
7038
7039        clear_problem_context(&pctx);
7040
7041        retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name,
7042                               sizeof(name)-1, 0, &ino);
7043        if (retval && !fix)
7044                return 0;
7045        if (!retval) {
7046                if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) {
7047                        ctx->lost_and_found = ino;
7048                        return ino;
7049                }
7050
7051                /* Lost+found isn't a directory! */
7052                if (!fix)
7053                        return 0;
7054                pctx.ino = ino;
7055                if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx))
7056                        return 0;
7057
7058                /* OK, unlink the old /lost+found file. */
7059                pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0);
7060                if (pctx.errcode) {
7061                        pctx.str = "ext2fs_unlink";
7062                        fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7063                        return 0;
7064                }
7065                dirinfo = e2fsck_get_dir_info(ctx, ino);
7066                if (dirinfo)
7067                        dirinfo->parent = 0;
7068                e2fsck_adjust_inode_count(ctx, ino, -1);
7069        } else if (retval != EXT2_ET_FILE_NOT_FOUND) {
7070                pctx.errcode = retval;
7071                fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx);
7072        }
7073        if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0))
7074                return 0;
7075
7076        /*
7077         * Read the inode and block bitmaps in; we'll be messing with
7078         * them.
7079         */
7080        e2fsck_read_bitmaps(ctx);
7081
7082        /*
7083         * First, find a free block
7084         */
7085        retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk);
7086        if (retval) {
7087                pctx.errcode = retval;
7088                fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx);
7089                return 0;
7090        }
7091        ext2fs_mark_block_bitmap(ctx->block_found_map, blk);
7092        ext2fs_block_alloc_stats(fs, blk, +1);
7093
7094        /*
7095         * Next find a free inode.
7096         */
7097        retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700,
7098                                  ctx->inode_used_map, &ino);
7099        if (retval) {
7100                pctx.errcode = retval;
7101                fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx);
7102                return 0;
7103        }
7104        ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino);
7105        ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino);
7106        ext2fs_inode_alloc_stats2(fs, ino, +1, 1);
7107
7108        /*
7109         * Now let's create the actual data block for the inode
7110         */
7111        retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block);
7112        if (retval) {
7113                pctx.errcode = retval;
7114                fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx);
7115                return 0;
7116        }
7117
7118        retval = ext2fs_write_dir_block(fs, blk, block);
7119        ext2fs_free_mem(&block);
7120        if (retval) {
7121                pctx.errcode = retval;
7122                fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx);
7123                return 0;
7124        }
7125
7126        /*
7127         * Set up the inode structure
7128         */
7129        memset(&inode, 0, sizeof(inode));
7130        inode.i_mode = 040700;
7131        inode.i_size = fs->blocksize;
7132        inode.i_atime = inode.i_ctime = inode.i_mtime = time(NULL);
7133        inode.i_links_count = 2;
7134        inode.i_blocks = fs->blocksize / 512;
7135        inode.i_block[0] = blk;
7136
7137        /*
7138         * Next, write out the inode.
7139         */
7140        pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode);
7141        if (pctx.errcode) {
7142                pctx.str = "ext2fs_write_inode";
7143                fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7144                return 0;
7145        }
7146        /*
7147         * Finally, create the directory link
7148         */
7149        pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR);
7150        if (pctx.errcode) {
7151                pctx.str = "ext2fs_link";
7152                fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx);
7153                return 0;
7154        }
7155
7156        /*
7157         * Miscellaneous bookkeeping that needs to be kept straight.
7158         */
7159        e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO);
7160        e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1);
7161        ext2fs_icount_store(ctx->inode_count, ino, 2);
7162        ext2fs_icount_store(ctx->inode_link_info, ino, 2);
7163        ctx->lost_and_found = ino;
7164        return ino;
7165}
7166
7167/*
7168 * This routine will connect a file to lost+found
7169 */
7170int e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino)
7171{
7172        ext2_filsys fs = ctx->fs;
7173        errcode_t       retval;
7174        char            name[80];
7175        struct problem_context  pctx;
7176        struct ext2_inode       inode;
7177        int             file_type = 0;
7178
7179        clear_problem_context(&pctx);
7180        pctx.ino = ino;
7181
7182        if (!ctx->bad_lost_and_found && !ctx->lost_and_found) {
7183                if (e2fsck_get_lost_and_found(ctx, 1) == 0)
7184                        ctx->bad_lost_and_found++;
7185        }
7186        if (ctx->bad_lost_and_found) {
7187                fix_problem(ctx, PR_3_NO_LPF, &pctx);
7188                return 1;
7189        }
7190
7191        sprintf(name, "#%u", ino);
7192        if (ext2fs_read_inode(fs, ino, &inode) == 0)
7193                file_type = ext2_file_type(inode.i_mode);
7194        retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type);
7195        if (retval == EXT2_ET_DIR_NO_SPACE) {
7196                if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx))
7197                        return 1;
7198                retval = e2fsck_expand_directory(ctx, ctx->lost_and_found,
7199                                                 1, 0);
7200                if (retval) {
7201                        pctx.errcode = retval;
7202                        fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx);
7203                        return 1;
7204                }
7205                retval = ext2fs_link(fs, ctx->lost_and_found, name,
7206                                     ino, file_type);
7207        }
7208        if (retval) {
7209                pctx.errcode = retval;
7210                fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx);
7211                return 1;
7212        }
7213        e2fsck_adjust_inode_count(ctx, ino, 1);
7214
7215        return 0;
7216}
7217
7218/*
7219 * Utility routine to adjust the inode counts on an inode.
7220 */
7221errcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj)
7222{
7223        ext2_filsys fs = ctx->fs;
7224        errcode_t               retval;
7225        struct ext2_inode       inode;
7226
7227        if (!ino)
7228                return 0;
7229
7230        retval = ext2fs_read_inode(fs, ino, &inode);
7231        if (retval)
7232                return retval;
7233
7234        if (adj == 1) {
7235                ext2fs_icount_increment(ctx->inode_count, ino, 0);
7236                if (inode.i_links_count == (__u16) ~0)
7237                        return 0;
7238                ext2fs_icount_increment(ctx->inode_link_info, ino, 0);
7239                inode.i_links_count++;
7240        } else if (adj == -1) {
7241                ext2fs_icount_decrement(ctx->inode_count, ino, 0);
7242                if (inode.i_links_count == 0)
7243                        return 0;
7244                ext2fs_icount_decrement(ctx->inode_link_info, ino, 0);
7245                inode.i_links_count--;
7246        }
7247
7248        retval = ext2fs_write_inode(fs, ino, &inode);
7249        if (retval)
7250                return retval;
7251
7252        return 0;
7253}
7254
7255/*
7256 * Fix parent --- this routine fixes up the parent of a directory.
7257 */
7258struct fix_dotdot_struct {
7259        ext2_filsys     fs;
7260        ext2_ino_t      parent;
7261        int             done;
7262        e2fsck_t        ctx;
7263};
7264
7265static int fix_dotdot_proc(struct ext2_dir_entry *dirent,
7266                           int  offset FSCK_ATTR((unused)),
7267                           int  blocksize FSCK_ATTR((unused)),
7268                           char *buf FSCK_ATTR((unused)),
7269                           void *priv_data)
7270{
7271        struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data;
7272        errcode_t       retval;
7273        struct problem_context pctx;
7274
7275        if ((dirent->name_len & 0xFF) != 2)
7276                return 0;
7277        if (strncmp(dirent->name, "..", 2))
7278                return 0;
7279
7280        clear_problem_context(&pctx);
7281
7282        retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1);
7283        if (retval) {
7284                pctx.errcode = retval;
7285                fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7286        }
7287        retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1);
7288        if (retval) {
7289                pctx.errcode = retval;
7290                fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx);
7291        }
7292        dirent->inode = fp->parent;
7293
7294        fp->done++;
7295        return DIRENT_ABORT | DIRENT_CHANGED;
7296}
7297
7298static void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ext2_ino_t parent)
7299{
7300        ext2_filsys fs = ctx->fs;
7301        errcode_t       retval;
7302        struct fix_dotdot_struct fp;
7303        struct problem_context pctx;
7304
7305        fp.fs = fs;
7306        fp.parent = parent;
7307        fp.done = 0;
7308        fp.ctx = ctx;
7309
7310        retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY,
7311                                    0, fix_dotdot_proc, &fp);
7312        if (retval || !fp.done) {
7313                clear_problem_context(&pctx);
7314                pctx.ino = dir->ino;
7315                pctx.errcode = retval;
7316                fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR :
7317                            PR_3_FIX_PARENT_NOFIND, &pctx);
7318                ext2fs_unmark_valid(fs);
7319        }
7320        dir->dotdot = parent;
7321}
7322
7323/*
7324 * These routines are responsible for expanding a /lost+found if it is
7325 * too small.
7326 */
7327
7328struct expand_dir_struct {
7329        int                     num;
7330        int                     guaranteed_size;
7331        int                     newblocks;
7332        int                     last_block;
7333        errcode_t               err;
7334        e2fsck_t                ctx;
7335};
7336
7337static int expand_dir_proc(ext2_filsys fs,
7338                           blk_t        *blocknr,
7339                           e2_blkcnt_t  blockcnt,
7340                           blk_t ref_block FSCK_ATTR((unused)),
7341                           int ref_offset FSCK_ATTR((unused)),
7342                           void *priv_data)
7343{
7344        struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data;
7345        blk_t   new_blk;
7346        static blk_t    last_blk = 0;
7347        char            *block;
7348        errcode_t       retval;
7349        e2fsck_t        ctx;
7350
7351        ctx = es->ctx;
7352
7353        if (es->guaranteed_size && blockcnt >= es->guaranteed_size)
7354                return BLOCK_ABORT;
7355
7356        if (blockcnt > 0)
7357                es->last_block = blockcnt;
7358        if (*blocknr) {
7359                last_blk = *blocknr;
7360                return 0;
7361        }
7362        retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map,
7363                                  &new_blk);
7364        if (retval) {
7365                es->err = retval;
7366                return BLOCK_ABORT;
7367        }
7368        if (blockcnt > 0) {
7369                retval = ext2fs_new_dir_block(fs, 0, 0, &block);
7370                if (retval) {
7371                        es->err = retval;
7372                        return BLOCK_ABORT;
7373                }
7374                es->num--;
7375                retval = ext2fs_write_dir_block(fs, new_blk, block);
7376        } else {
7377                retval = ext2fs_get_mem(fs->blocksize, &block);
7378                if (retval) {
7379                        es->err = retval;
7380                        return BLOCK_ABORT;
7381                }
7382                memset(block, 0, fs->blocksize);
7383                retval = io_channel_write_blk(fs->io, new_blk, 1, block);
7384        }
7385        if (retval) {
7386                es->err = retval;
7387                return BLOCK_ABORT;
7388        }
7389        ext2fs_free_mem(&block);
7390        *blocknr = new_blk;
7391        ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk);
7392        ext2fs_block_alloc_stats(fs, new_blk, +1);
7393        es->newblocks++;
7394
7395        if (es->num == 0)
7396                return (BLOCK_CHANGED | BLOCK_ABORT);
7397        else
7398                return BLOCK_CHANGED;
7399}
7400
7401errcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir,
7402                                  int num, int guaranteed_size)
7403{
7404        ext2_filsys fs = ctx->fs;
7405        errcode_t       retval;
7406        struct expand_dir_struct es;
7407        struct ext2_inode       inode;
7408
7409        if (!(fs->flags & EXT2_FLAG_RW))
7410                return EXT2_ET_RO_FILSYS;
7411
7412        /*
7413         * Read the inode and block bitmaps in; we'll be messing with
7414         * them.
7415         */
7416        e2fsck_read_bitmaps(ctx);
7417
7418        retval = ext2fs_check_directory(fs, dir);
7419        if (retval)
7420                return retval;
7421
7422        es.num = num;
7423        es.guaranteed_size = guaranteed_size;
7424        es.last_block = 0;
7425        es.err = 0;
7426        es.newblocks = 0;
7427        es.ctx = ctx;
7428
7429        retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND,
7430                                       0, expand_dir_proc, &es);
7431
7432        if (es.err)
7433                return es.err;
7434
7435        /*
7436         * Update the size and block count fields in the inode.
7437         */
7438        retval = ext2fs_read_inode(fs, dir, &inode);
7439        if (retval)
7440                return retval;
7441
7442        inode.i_size = (es.last_block + 1) * fs->blocksize;
7443        inode.i_blocks += (fs->blocksize / 512) * es.newblocks;
7444
7445        e2fsck_write_inode(ctx, dir, &inode, "expand_directory");
7446
7447        return 0;
7448}
7449
7450/*
7451 * pass4.c -- pass #4 of e2fsck: Check reference counts
7452 *
7453 * Pass 4 frees the following data structures:
7454 *      - A bitmap of which inodes are imagic inodes.   (inode_imagic_map)
7455 */
7456
7457/*
7458 * This routine is called when an inode is not connected to the
7459 * directory tree.
7460 *
7461 * This subroutine returns 1 then the caller shouldn't bother with the
7462 * rest of the pass 4 tests.
7463 */
7464static int disconnect_inode(e2fsck_t ctx, ext2_ino_t i)
7465{
7466        ext2_filsys fs = ctx->fs;
7467        struct ext2_inode       inode;
7468        struct problem_context  pctx;
7469
7470        e2fsck_read_inode(ctx, i, &inode, "pass4: disconnect_inode");
7471        clear_problem_context(&pctx);
7472        pctx.ino = i;
7473        pctx.inode = &inode;
7474
7475        /*
7476         * Offer to delete any zero-length files that does not have
7477         * blocks.  If there is an EA block, it might have useful
7478         * information, so we won't prompt to delete it, but let it be
7479         * reconnected to lost+found.
7480         */
7481        if (!inode.i_blocks && (LINUX_S_ISREG(inode.i_mode) ||
7482                                LINUX_S_ISDIR(inode.i_mode))) {
7483                if (fix_problem(ctx, PR_4_ZERO_LEN_INODE, &pctx)) {
7484                        ext2fs_icount_store(ctx->inode_link_info, i, 0);
7485                        inode.i_links_count = 0;
7486                        inode.i_dtime = time(NULL);
7487                        e2fsck_write_inode(ctx, i, &inode,
7488                                           "disconnect_inode");
7489                        /*
7490                         * Fix up the bitmaps...
7491                         */
7492                        e2fsck_read_bitmaps(ctx);
7493                        ext2fs_unmark_inode_bitmap(ctx->inode_used_map, i);
7494                        ext2fs_unmark_inode_bitmap(ctx->inode_dir_map, i);
7495                        ext2fs_inode_alloc_stats2(fs, i, -1,
7496                                                  LINUX_S_ISDIR(inode.i_mode));
7497                        return 0;
7498                }
7499        }
7500
7501        /*
7502         * Prompt to reconnect.
7503         */
7504        if (fix_problem(ctx, PR_4_UNATTACHED_INODE, &pctx)) {
7505                if (e2fsck_reconnect_file(ctx, i))
7506                        ext2fs_unmark_valid(fs);
7507        } else {
7508                /*
7509                 * If we don't attach the inode, then skip the
7510                 * i_links_test since there's no point in trying to
7511                 * force i_links_count to zero.
7512                 */
7513                ext2fs_unmark_valid(fs);
7514                return 1;
7515        }
7516        return 0;
7517}
7518
7519
7520static void e2fsck_pass4(e2fsck_t ctx)
7521{
7522        ext2_filsys fs = ctx->fs;
7523        ext2_ino_t      i;
7524        struct ext2_inode       inode;
7525        struct problem_context  pctx;
7526        __u16   link_count, link_counted;
7527        char    *buf = 0;
7528        int     group, maxgroup;
7529
7530        /* Pass 4 */
7531
7532        clear_problem_context(&pctx);
7533
7534        if (!(ctx->options & E2F_OPT_PREEN))
7535                fix_problem(ctx, PR_4_PASS_HEADER, &pctx);
7536
7537        group = 0;
7538        maxgroup = fs->group_desc_count;
7539        if (ctx->progress)
7540                if ((ctx->progress)(ctx, 4, 0, maxgroup))
7541                        return;
7542
7543        for (i=1; i <= fs->super->s_inodes_count; i++) {
7544                if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
7545                        return;
7546                if ((i % fs->super->s_inodes_per_group) == 0) {
7547                        group++;
7548                        if (ctx->progress)
7549                                if ((ctx->progress)(ctx, 4, group, maxgroup))
7550                                        return;
7551                }
7552                if (i == EXT2_BAD_INO ||
7553                    (i > EXT2_ROOT_INO && i < EXT2_FIRST_INODE(fs->super)))
7554                        continue;
7555                if (!(ext2fs_test_inode_bitmap(ctx->inode_used_map, i)) ||
7556                    (ctx->inode_imagic_map &&
7557                     ext2fs_test_inode_bitmap(ctx->inode_imagic_map, i)))
7558                        continue;
7559                ext2fs_icount_fetch(ctx->inode_link_info, i, &link_count);
7560                ext2fs_icount_fetch(ctx->inode_count, i, &link_counted);
7561                if (link_counted == 0) {
7562                        if (!buf)
7563                                buf = e2fsck_allocate_memory(ctx,
7564                                     fs->blocksize, "bad_inode buffer");
7565                        if (e2fsck_process_bad_inode(ctx, 0, i, buf))
7566                                continue;
7567                        if (disconnect_inode(ctx, i))
7568                                continue;
7569                        ext2fs_icount_fetch(ctx->inode_link_info, i,
7570                                            &link_count);
7571                        ext2fs_icount_fetch(ctx->inode_count, i,
7572                                            &link_counted);
7573                }
7574                if (link_counted != link_count) {
7575                        e2fsck_read_inode(ctx, i, &inode, "pass4");
7576                        pctx.ino = i;
7577                        pctx.inode = &inode;
7578                        if (link_count != inode.i_links_count) {
7579                                pctx.num = link_count;
7580                                fix_problem(ctx,
7581                                            PR_4_INCONSISTENT_COUNT, &pctx);
7582                        }
7583                        pctx.num = link_counted;
7584                        if (fix_problem(ctx, PR_4_BAD_REF_COUNT, &pctx)) {
7585                                inode.i_links_count = link_counted;
7586                                e2fsck_write_inode(ctx, i, &inode, "pass4");
7587                        }
7588                }
7589        }
7590        ext2fs_free_icount(ctx->inode_link_info); ctx->inode_link_info = 0;
7591        ext2fs_free_icount(ctx->inode_count); ctx->inode_count = 0;
7592        ext2fs_free_inode_bitmap(ctx->inode_imagic_map);
7593        ctx->inode_imagic_map = 0;
7594        ext2fs_free_mem(&buf);
7595}
7596
7597/*
7598 * pass5.c --- check block and inode bitmaps against on-disk bitmaps
7599 */
7600
7601#define NO_BLK ((blk_t) -1)
7602
7603static void print_bitmap_problem(e2fsck_t ctx, int problem,
7604                            struct problem_context *pctx)
7605{
7606        switch (problem) {
7607        case PR_5_BLOCK_UNUSED:
7608                if (pctx->blk == pctx->blk2)
7609                        pctx->blk2 = 0;
7610                else
7611                        problem = PR_5_BLOCK_RANGE_UNUSED;
7612                break;
7613        case PR_5_BLOCK_USED:
7614                if (pctx->blk == pctx->blk2)
7615                        pctx->blk2 = 0;
7616                else
7617                        problem = PR_5_BLOCK_RANGE_USED;
7618                break;
7619        case PR_5_INODE_UNUSED:
7620                if (pctx->ino == pctx->ino2)
7621                        pctx->ino2 = 0;
7622                else
7623                        problem = PR_5_INODE_RANGE_UNUSED;
7624                break;
7625        case PR_5_INODE_USED:
7626                if (pctx->ino == pctx->ino2)
7627                        pctx->ino2 = 0;
7628                else
7629                        problem = PR_5_INODE_RANGE_USED;
7630                break;
7631        }
7632        fix_problem(ctx, problem, pctx);
7633        pctx->blk = pctx->blk2 = NO_BLK;
7634        pctx->ino = pctx->ino2 = 0;
7635}
7636
7637static void check_block_bitmaps(e2fsck_t ctx)
7638{
7639        ext2_filsys fs = ctx->fs;
7640        blk_t   i;
7641        int     *free_array;
7642        int     group = 0;
7643        unsigned int    blocks = 0;
7644        unsigned int    free_blocks = 0;
7645        int     group_free = 0;
7646        int     actual, bitmap;
7647        struct problem_context  pctx;
7648        int     problem, save_problem, fixit, had_problem;
7649        errcode_t       retval;
7650
7651        clear_problem_context(&pctx);
7652        free_array = (int *) e2fsck_allocate_memory(ctx,
7653            fs->group_desc_count * sizeof(int), "free block count array");
7654
7655        if ((fs->super->s_first_data_block <
7656             ext2fs_get_block_bitmap_start(ctx->block_found_map)) ||
7657            (fs->super->s_blocks_count-1 >
7658             ext2fs_get_block_bitmap_end(ctx->block_found_map))) {
7659                pctx.num = 1;
7660                pctx.blk = fs->super->s_first_data_block;
7661                pctx.blk2 = fs->super->s_blocks_count -1;
7662                pctx.ino = ext2fs_get_block_bitmap_start(ctx->block_found_map);
7663                pctx.ino2 = ext2fs_get_block_bitmap_end(ctx->block_found_map);
7664                fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7665
7666                ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7667                return;
7668        }
7669
7670        if ((fs->super->s_first_data_block <
7671             ext2fs_get_block_bitmap_start(fs->block_map)) ||
7672            (fs->super->s_blocks_count-1 >
7673             ext2fs_get_block_bitmap_end(fs->block_map))) {
7674                pctx.num = 2;
7675                pctx.blk = fs->super->s_first_data_block;
7676                pctx.blk2 = fs->super->s_blocks_count -1;
7677                pctx.ino = ext2fs_get_block_bitmap_start(fs->block_map);
7678                pctx.ino2 = ext2fs_get_block_bitmap_end(fs->block_map);
7679                fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7680
7681                ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7682                return;
7683        }
7684
7685redo_counts:
7686        had_problem = 0;
7687        save_problem = 0;
7688        pctx.blk = pctx.blk2 = NO_BLK;
7689        for (i = fs->super->s_first_data_block;
7690             i < fs->super->s_blocks_count;
7691             i++) {
7692                actual = ext2fs_fast_test_block_bitmap(ctx->block_found_map, i);
7693                bitmap = ext2fs_fast_test_block_bitmap(fs->block_map, i);
7694
7695                if (actual == bitmap)
7696                        goto do_counts;
7697
7698                if (!actual && bitmap) {
7699                        /*
7700                         * Block not used, but marked in use in the bitmap.
7701                         */
7702                        problem = PR_5_BLOCK_UNUSED;
7703                } else {
7704                        /*
7705                         * Block used, but not marked in use in the bitmap.
7706                         */
7707                        problem = PR_5_BLOCK_USED;
7708                }
7709                if (pctx.blk == NO_BLK) {
7710                        pctx.blk = pctx.blk2 = i;
7711                        save_problem = problem;
7712                } else {
7713                        if ((problem == save_problem) &&
7714                            (pctx.blk2 == i-1))
7715                                pctx.blk2++;
7716                        else {
7717                                print_bitmap_problem(ctx, save_problem, &pctx);
7718                                pctx.blk = pctx.blk2 = i;
7719                                save_problem = problem;
7720                        }
7721                }
7722                ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7723                had_problem++;
7724
7725        do_counts:
7726                if (!bitmap) {
7727                        group_free++;
7728                        free_blocks++;
7729                }
7730                blocks ++;
7731                if ((blocks == fs->super->s_blocks_per_group) ||
7732                    (i == fs->super->s_blocks_count-1)) {
7733                        free_array[group] = group_free;
7734                        group ++;
7735                        blocks = 0;
7736                        group_free = 0;
7737                        if (ctx->progress)
7738                                if ((ctx->progress)(ctx, 5, group,
7739                                                    fs->group_desc_count*2))
7740                                        return;
7741                }
7742        }
7743        if (pctx.blk != NO_BLK)
7744                print_bitmap_problem(ctx, save_problem, &pctx);
7745        if (had_problem)
7746                fixit = end_problem_latch(ctx, PR_LATCH_BBITMAP);
7747        else
7748                fixit = -1;
7749        ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7750
7751        if (fixit == 1) {
7752                ext2fs_free_block_bitmap(fs->block_map);
7753                retval = ext2fs_copy_bitmap(ctx->block_found_map,
7754                                                  &fs->block_map);
7755                if (retval) {
7756                        clear_problem_context(&pctx);
7757                        fix_problem(ctx, PR_5_COPY_BBITMAP_ERROR, &pctx);
7758                        ctx->flags |= E2F_FLAG_ABORT;
7759                        return;
7760                }
7761                ext2fs_set_bitmap_padding(fs->block_map);
7762                ext2fs_mark_bb_dirty(fs);
7763
7764                /* Redo the counts */
7765                blocks = 0; free_blocks = 0; group_free = 0; group = 0;
7766                memset(free_array, 0, fs->group_desc_count * sizeof(int));
7767                goto redo_counts;
7768        } else if (fixit == 0)
7769                ext2fs_unmark_valid(fs);
7770
7771        for (i = 0; i < fs->group_desc_count; i++) {
7772                if (free_array[i] != fs->group_desc[i].bg_free_blocks_count) {
7773                        pctx.group = i;
7774                        pctx.blk = fs->group_desc[i].bg_free_blocks_count;
7775                        pctx.blk2 = free_array[i];
7776
7777                        if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT_GROUP,
7778                                        &pctx)) {
7779                                fs->group_desc[i].bg_free_blocks_count =
7780                                        free_array[i];
7781                                ext2fs_mark_super_dirty(fs);
7782                        } else
7783                                ext2fs_unmark_valid(fs);
7784                }
7785        }
7786        if (free_blocks != fs->super->s_free_blocks_count) {
7787                pctx.group = 0;
7788                pctx.blk = fs->super->s_free_blocks_count;
7789                pctx.blk2 = free_blocks;
7790
7791                if (fix_problem(ctx, PR_5_FREE_BLOCK_COUNT, &pctx)) {
7792                        fs->super->s_free_blocks_count = free_blocks;
7793                        ext2fs_mark_super_dirty(fs);
7794                } else
7795                        ext2fs_unmark_valid(fs);
7796        }
7797        ext2fs_free_mem(&free_array);
7798}
7799
7800static void check_inode_bitmaps(e2fsck_t ctx)
7801{
7802        ext2_filsys fs = ctx->fs;
7803        ext2_ino_t      i;
7804        unsigned int    free_inodes = 0;
7805        int             group_free = 0;
7806        int             dirs_count = 0;
7807        int             group = 0;
7808        unsigned int    inodes = 0;
7809        int             *free_array;
7810        int             *dir_array;
7811        int             actual, bitmap;
7812        errcode_t       retval;
7813        struct problem_context  pctx;
7814        int             problem, save_problem, fixit, had_problem;
7815
7816        clear_problem_context(&pctx);
7817        free_array = (int *) e2fsck_allocate_memory(ctx,
7818            fs->group_desc_count * sizeof(int), "free inode count array");
7819
7820        dir_array = (int *) e2fsck_allocate_memory(ctx,
7821           fs->group_desc_count * sizeof(int), "directory count array");
7822
7823        if ((1 < ext2fs_get_inode_bitmap_start(ctx->inode_used_map)) ||
7824            (fs->super->s_inodes_count >
7825             ext2fs_get_inode_bitmap_end(ctx->inode_used_map))) {
7826                pctx.num = 3;
7827                pctx.blk = 1;
7828                pctx.blk2 = fs->super->s_inodes_count;
7829                pctx.ino = ext2fs_get_inode_bitmap_start(ctx->inode_used_map);
7830                pctx.ino2 = ext2fs_get_inode_bitmap_end(ctx->inode_used_map);
7831                fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7832
7833                ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7834                return;
7835        }
7836        if ((1 < ext2fs_get_inode_bitmap_start(fs->inode_map)) ||
7837            (fs->super->s_inodes_count >
7838             ext2fs_get_inode_bitmap_end(fs->inode_map))) {
7839                pctx.num = 4;
7840                pctx.blk = 1;
7841                pctx.blk2 = fs->super->s_inodes_count;
7842                pctx.ino = ext2fs_get_inode_bitmap_start(fs->inode_map);
7843                pctx.ino2 = ext2fs_get_inode_bitmap_end(fs->inode_map);
7844                fix_problem(ctx, PR_5_BMAP_ENDPOINTS, &pctx);
7845
7846                ctx->flags |= E2F_FLAG_ABORT; /* fatal */
7847                return;
7848        }
7849
7850redo_counts:
7851        had_problem = 0;
7852        save_problem = 0;
7853        pctx.ino = pctx.ino2 = 0;
7854        for (i = 1; i <= fs->super->s_inodes_count; i++) {
7855                actual = ext2fs_fast_test_inode_bitmap(ctx->inode_used_map, i);
7856                bitmap = ext2fs_fast_test_inode_bitmap(fs->inode_map, i);
7857
7858                if (actual == bitmap)
7859                        goto do_counts;
7860
7861                if (!actual && bitmap) {
7862                        /*
7863                         * Inode wasn't used, but marked in bitmap
7864                         */
7865                        problem = PR_5_INODE_UNUSED;
7866                } else /* if (actual && !bitmap) */ {
7867                        /*
7868                         * Inode used, but not in bitmap
7869                         */
7870                        problem = PR_5_INODE_USED;
7871                }
7872                if (pctx.ino == 0) {
7873                        pctx.ino = pctx.ino2 = i;
7874                        save_problem = problem;
7875                } else {
7876                        if ((problem == save_problem) &&
7877                            (pctx.ino2 == i-1))
7878                                pctx.ino2++;
7879                        else {
7880                                print_bitmap_problem(ctx, save_problem, &pctx);
7881                                pctx.ino = pctx.ino2 = i;
7882                                save_problem = problem;
7883                        }
7884                }
7885                ctx->flags |= E2F_FLAG_PROG_SUPPRESS;
7886                had_problem++;
7887
7888do_counts:
7889                if (!bitmap) {
7890                        group_free++;
7891                        free_inodes++;
7892                } else {
7893                        if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, i))
7894                                dirs_count++;
7895                }
7896                inodes++;
7897                if ((inodes == fs->super->s_inodes_per_group) ||
7898                    (i == fs->super->s_inodes_count)) {
7899                        free_array[group] = group_free;
7900                        dir_array[group] = dirs_count;
7901                        group ++;
7902                        inodes = 0;
7903                        group_free = 0;
7904                        dirs_count = 0;
7905                        if (ctx->progress)
7906                                if ((ctx->progress)(ctx, 5,
7907                                            group + fs->group_desc_count,
7908                                            fs->group_desc_count*2))
7909                                        return;
7910                }
7911        }
7912        if (pctx.ino)
7913                print_bitmap_problem(ctx, save_problem, &pctx);
7914
7915        if (had_problem)
7916                fixit = end_problem_latch(ctx, PR_LATCH_IBITMAP);
7917        else
7918                fixit = -1;
7919        ctx->flags &= ~E2F_FLAG_PROG_SUPPRESS;
7920
7921        if (fixit == 1) {
7922                ext2fs_free_inode_bitmap(fs->inode_map);
7923                retval = ext2fs_copy_bitmap(ctx->inode_used_map,
7924                                                  &fs->inode_map);
7925                if (retval) {
7926                        clear_problem_context(&pctx);
7927                        fix_problem(ctx, PR_5_COPY_IBITMAP_ERROR, &pctx);
7928                        ctx->flags |= E2F_FLAG_ABORT;
7929                        return;
7930                }
7931                ext2fs_set_bitmap_padding(fs->inode_map);
7932                ext2fs_mark_ib_dirty(fs);
7933
7934                /* redo counts */
7935                inodes = 0; free_inodes = 0; group_free = 0;
7936                dirs_count = 0; group = 0;
7937                memset(free_array, 0, fs->group_desc_count * sizeof(int));
7938                memset(dir_array, 0, fs->group_desc_count * sizeof(int));
7939                goto redo_counts;
7940        } else if (fixit == 0)
7941                ext2fs_unmark_valid(fs);
7942
7943        for (i = 0; i < fs->group_desc_count; i++) {
7944                if (free_array[i] != fs->group_desc[i].bg_free_inodes_count) {
7945                        pctx.group = i;
7946                        pctx.ino = fs->group_desc[i].bg_free_inodes_count;
7947                        pctx.ino2 = free_array[i];
7948                        if (fix_problem(ctx, PR_5_FREE_INODE_COUNT_GROUP,
7949                                        &pctx)) {
7950                                fs->group_desc[i].bg_free_inodes_count =
7951                                        free_array[i];
7952                                ext2fs_mark_super_dirty(fs);
7953                        } else
7954                                ext2fs_unmark_valid(fs);
7955                }
7956                if (dir_array[i] != fs->group_desc[i].bg_used_dirs_count) {
7957                        pctx.group = i;
7958                        pctx.ino = fs->group_desc[i].bg_used_dirs_count;
7959                        pctx.ino2 = dir_array[i];
7960
7961                        if (fix_problem(ctx, PR_5_FREE_DIR_COUNT_GROUP,
7962                                        &pctx)) {
7963                                fs->group_desc[i].bg_used_dirs_count =
7964                                        dir_array[i];
7965                                ext2fs_mark_super_dirty(fs);
7966                        } else
7967                                ext2fs_unmark_valid(fs);
7968                }
7969        }
7970        if (free_inodes != fs->super->s_free_inodes_count) {
7971                pctx.group = -1;
7972                pctx.ino = fs->super->s_free_inodes_count;
7973                pctx.ino2 = free_inodes;
7974
7975                if (fix_problem(ctx, PR_5_FREE_INODE_COUNT, &pctx)) {
7976                        fs->super->s_free_inodes_count = free_inodes;
7977                        ext2fs_mark_super_dirty(fs);
7978                } else
7979                        ext2fs_unmark_valid(fs);
7980        }
7981        ext2fs_free_mem(&free_array);
7982        ext2fs_free_mem(&dir_array);
7983}
7984
7985static void check_inode_end(e2fsck_t ctx)
7986{
7987        ext2_filsys fs = ctx->fs;
7988        ext2_ino_t      end, save_inodes_count, i;
7989        struct problem_context  pctx;
7990
7991        clear_problem_context(&pctx);
7992
7993        end = EXT2_INODES_PER_GROUP(fs->super) * fs->group_desc_count;
7994        pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map, end,
7995                                                     &save_inodes_count);
7996        if (pctx.errcode) {
7997                pctx.num = 1;
7998                fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
7999                ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8000                return;
8001        }
8002        if (save_inodes_count == end)
8003                return;
8004
8005        for (i = save_inodes_count + 1; i <= end; i++) {
8006                if (!ext2fs_test_inode_bitmap(fs->inode_map, i)) {
8007                        if (fix_problem(ctx, PR_5_INODE_BMAP_PADDING, &pctx)) {
8008                                for (i = save_inodes_count + 1; i <= end; i++)
8009                                        ext2fs_mark_inode_bitmap(fs->inode_map,
8010                                                                 i);
8011                                ext2fs_mark_ib_dirty(fs);
8012                        } else
8013                                ext2fs_unmark_valid(fs);
8014                        break;
8015                }
8016        }
8017
8018        pctx.errcode = ext2fs_fudge_inode_bitmap_end(fs->inode_map,
8019                                                     save_inodes_count, 0);
8020        if (pctx.errcode) {
8021                pctx.num = 2;
8022                fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8023                ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8024                return;
8025        }
8026}
8027
8028static void check_block_end(e2fsck_t ctx)
8029{
8030        ext2_filsys fs = ctx->fs;
8031        blk_t   end, save_blocks_count, i;
8032        struct problem_context  pctx;
8033
8034        clear_problem_context(&pctx);
8035
8036        end = fs->block_map->start +
8037                (EXT2_BLOCKS_PER_GROUP(fs->super) * fs->group_desc_count) - 1;
8038        pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map, end,
8039                                                     &save_blocks_count);
8040        if (pctx.errcode) {
8041                pctx.num = 3;
8042                fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8043                ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8044                return;
8045        }
8046        if (save_blocks_count == end)
8047                return;
8048
8049        for (i = save_blocks_count + 1; i <= end; i++) {
8050                if (!ext2fs_test_block_bitmap(fs->block_map, i)) {
8051                        if (fix_problem(ctx, PR_5_BLOCK_BMAP_PADDING, &pctx)) {
8052                                for (i = save_blocks_count + 1; i <= end; i++)
8053                                        ext2fs_mark_block_bitmap(fs->block_map,
8054                                                                 i);
8055                                ext2fs_mark_bb_dirty(fs);
8056                        } else
8057                                ext2fs_unmark_valid(fs);
8058                        break;
8059                }
8060        }
8061
8062        pctx.errcode = ext2fs_fudge_block_bitmap_end(fs->block_map,
8063                                                     save_blocks_count, 0);
8064        if (pctx.errcode) {
8065                pctx.num = 4;
8066                fix_problem(ctx, PR_5_FUDGE_BITMAP_ERROR, &pctx);
8067                ctx->flags |= E2F_FLAG_ABORT; /* fatal */
8068                return;
8069        }
8070}
8071
8072static void e2fsck_pass5(e2fsck_t ctx)
8073{
8074        struct problem_context  pctx;
8075
8076        /* Pass 5 */
8077
8078        clear_problem_context(&pctx);
8079
8080        if (!(ctx->options & E2F_OPT_PREEN))
8081                fix_problem(ctx, PR_5_PASS_HEADER, &pctx);
8082
8083        if (ctx->progress)
8084                if ((ctx->progress)(ctx, 5, 0, ctx->fs->group_desc_count*2))
8085                        return;
8086
8087        e2fsck_read_bitmaps(ctx);
8088
8089        check_block_bitmaps(ctx);
8090        if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8091                return;
8092        check_inode_bitmaps(ctx);
8093        if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8094                return;
8095        check_inode_end(ctx);
8096        if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8097                return;
8098        check_block_end(ctx);
8099        if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
8100                return;
8101
8102        ext2fs_free_inode_bitmap(ctx->inode_used_map);
8103        ctx->inode_used_map = 0;
8104        ext2fs_free_inode_bitmap(ctx->inode_dir_map);
8105        ctx->inode_dir_map = 0;
8106        ext2fs_free_block_bitmap(ctx->block_found_map);
8107        ctx->block_found_map = 0;
8108}
8109
8110/*
8111 * problem.c --- report filesystem problems to the user
8112 */
8113
8114#define PR_PREEN_OK     0x000001 /* Don't need to do preenhalt */
8115#define PR_NO_OK        0x000002 /* If user answers no, don't make fs invalid */
8116#define PR_NO_DEFAULT   0x000004 /* Default to no */
8117#define PR_MSG_ONLY     0x000008 /* Print message only */
8118
8119/* Bit positions 0x000ff0 are reserved for the PR_LATCH flags */
8120
8121#define PR_FATAL        0x001000 /* Fatal error */
8122#define PR_AFTER_CODE   0x002000 /* After asking the first question, */
8123                                 /* ask another */
8124#define PR_PREEN_NOMSG  0x004000 /* Don't print a message if we're preening */
8125#define PR_NOCOLLATE    0x008000 /* Don't collate answers for this latch */
8126#define PR_NO_NOMSG     0x010000 /* Don't print a message if e2fsck -n */
8127#define PR_PREEN_NO     0x020000 /* Use No as an answer if preening */
8128#define PR_PREEN_NOHDR  0x040000 /* Don't print the preen header */
8129
8130
8131#define PROMPT_NONE     0
8132#define PROMPT_FIX      1
8133#define PROMPT_CLEAR    2
8134#define PROMPT_RELOCATE 3
8135#define PROMPT_ALLOCATE 4
8136#define PROMPT_EXPAND   5
8137#define PROMPT_CONNECT  6
8138#define PROMPT_CREATE   7
8139#define PROMPT_SALVAGE  8
8140#define PROMPT_TRUNCATE 9
8141#define PROMPT_CLEAR_INODE 10
8142#define PROMPT_ABORT    11
8143#define PROMPT_SPLIT    12
8144#define PROMPT_CONTINUE 13
8145#define PROMPT_CLONE    14
8146#define PROMPT_DELETE   15
8147#define PROMPT_SUPPRESS 16
8148#define PROMPT_UNLINK   17
8149#define PROMPT_CLEAR_HTREE 18
8150#define PROMPT_RECREATE 19
8151#define PROMPT_NULL     20
8152
8153struct e2fsck_problem {
8154        problem_t       e2p_code;
8155        const char *    e2p_description;
8156        char            prompt;
8157        int             flags;
8158        problem_t       second_code;
8159};
8160
8161struct latch_descr {
8162        int             latch_code;
8163        problem_t       question;
8164        problem_t       end_message;
8165        int             flags;
8166};
8167
8168/*
8169 * These are the prompts which are used to ask the user if they want
8170 * to fix a problem.
8171 */
8172static const char *const prompt[] = {
8173        N_("(no prompt)"),      /* 0 */
8174        N_("Fix"),              /* 1 */
8175        N_("Clear"),            /* 2 */
8176        N_("Relocate"),         /* 3 */
8177        N_("Allocate"),         /* 4 */
8178        N_("Expand"),           /* 5 */
8179        N_("Connect to /lost+found"), /* 6 */
8180        N_("Create"),           /* 7 */
8181        N_("Salvage"),          /* 8 */
8182        N_("Truncate"),         /* 9 */
8183        N_("Clear inode"),      /* 10 */
8184        N_("Abort"),            /* 11 */
8185        N_("Split"),            /* 12 */
8186        N_("Continue"),         /* 13 */
8187        N_("Clone multiply-claimed blocks"), /* 14 */
8188        N_("Delete file"),      /* 15 */
8189        N_("Suppress messages"),/* 16 */
8190        N_("Unlink"),           /* 17 */
8191        N_("Clear HTree index"),/* 18 */
8192        N_("Recreate"),         /* 19 */
8193        "",                     /* 20 */
8194};
8195
8196/*
8197 * These messages are printed when we are preen mode and we will be
8198 * automatically fixing the problem.
8199 */
8200static const char *const preen_msg[] = {
8201        N_("(NONE)"),           /* 0 */
8202        N_("FIXED"),            /* 1 */
8203        N_("CLEARED"),          /* 2 */
8204        N_("RELOCATED"),        /* 3 */
8205        N_("ALLOCATED"),        /* 4 */
8206        N_("EXPANDED"),         /* 5 */
8207        N_("RECONNECTED"),      /* 6 */
8208        N_("CREATED"),          /* 7 */
8209        N_("SALVAGED"),         /* 8 */
8210        N_("TRUNCATED"),        /* 9 */
8211        N_("INODE CLEARED"),    /* 10 */
8212        N_("ABORTED"),          /* 11 */
8213        N_("SPLIT"),            /* 12 */
8214        N_("CONTINUING"),       /* 13 */
8215        N_("MULTIPLY-CLAIMED BLOCKS CLONED"), /* 14 */
8216        N_("FILE DELETED"),     /* 15 */
8217        N_("SUPPRESSED"),       /* 16 */
8218        N_("UNLINKED"),         /* 17 */
8219        N_("HTREE INDEX CLEARED"),/* 18 */
8220        N_("WILL RECREATE"),    /* 19 */
8221        "",                     /* 20 */
8222};
8223
8224static const struct e2fsck_problem problem_table[] = {
8225
8226        /* Pre-Pass 1 errors */
8227
8228        /* Block bitmap not in group */
8229        { PR_0_BB_NOT_GROUP, N_("@b @B for @g %g is not in @g.  (@b %b)\n"),
8230          PROMPT_RELOCATE, PR_LATCH_RELOC },
8231
8232        /* Inode bitmap not in group */
8233        { PR_0_IB_NOT_GROUP, N_("@i @B for @g %g is not in @g.  (@b %b)\n"),
8234          PROMPT_RELOCATE, PR_LATCH_RELOC },
8235
8236        /* Inode table not in group */
8237        { PR_0_ITABLE_NOT_GROUP,
8238          N_("@i table for @g %g is not in @g.  (@b %b)\n"
8239          "WARNING: SEVERE DATA LOSS POSSIBLE.\n"),
8240          PROMPT_RELOCATE, PR_LATCH_RELOC },
8241
8242        /* Superblock corrupt */
8243        { PR_0_SB_CORRUPT,
8244          N_("\nThe @S could not be read or does not describe a correct ext2\n"
8245          "@f.  If the @v is valid and it really contains an ext2\n"
8246          "@f (and not swap or ufs or something else), then the @S\n"
8247          "is corrupt, and you might try running e2fsck with an alternate @S:\n"
8248          "    e2fsck -b %S <@v>\n\n"),
8249          PROMPT_NONE, PR_FATAL },
8250
8251        /* Filesystem size is wrong */
8252        { PR_0_FS_SIZE_WRONG,
8253          N_("The @f size (according to the @S) is %b @bs\n"
8254          "The physical size of the @v is %c @bs\n"
8255          "Either the @S or the partition table is likely to be corrupt!\n"),
8256          PROMPT_ABORT, 0 },
8257
8258        /* Fragments not supported */
8259        { PR_0_NO_FRAGMENTS,
8260          N_("@S @b_size = %b, fragsize = %c.\n"
8261          "This version of e2fsck does not support fragment sizes different\n"
8262          "from the @b size.\n"),
8263          PROMPT_NONE, PR_FATAL },
8264
8265          /* Bad blocks_per_group */
8266        { PR_0_BLOCKS_PER_GROUP,
8267          N_("@S @bs_per_group = %b, should have been %c\n"),
8268          PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8269
8270        /* Bad first_data_block */
8271        { PR_0_FIRST_DATA_BLOCK,
8272          N_("@S first_data_@b = %b, should have been %c\n"),
8273          PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8274
8275        /* Adding UUID to filesystem */
8276        { PR_0_ADD_UUID,
8277          N_("@f did not have a UUID; generating one.\n\n"),
8278          PROMPT_NONE, 0 },
8279
8280        /* Relocate hint */
8281        { PR_0_RELOCATE_HINT,
8282          N_("Note: if several inode or block bitmap blocks or part\n"
8283          "of the inode table require relocation, you may wish to try\n"
8284          "running e2fsck with the '-b %S' option first.  The problem\n"
8285          "may lie only with the primary block group descriptors, and\n"
8286          "the backup block group descriptors may be OK.\n\n"),
8287          PROMPT_NONE, PR_PREEN_OK | PR_NOCOLLATE },
8288
8289        /* Miscellaneous superblock corruption */
8290        { PR_0_MISC_CORRUPT_SUPER,
8291          N_("Corruption found in @S.  (%s = %N).\n"),
8292          PROMPT_NONE, PR_AFTER_CODE, PR_0_SB_CORRUPT },
8293
8294        /* Error determing physical device size of filesystem */
8295        { PR_0_GETSIZE_ERROR,
8296          N_("Error determining size of the physical @v: %m\n"),
8297          PROMPT_NONE, PR_FATAL },
8298
8299        /* Inode count in superblock is incorrect */
8300        { PR_0_INODE_COUNT_WRONG,
8301          N_("@i count in @S is %i, @s %j.\n"),
8302          PROMPT_FIX, 0 },
8303
8304        { PR_0_HURD_CLEAR_FILETYPE,
8305          N_("The Hurd does not support the filetype feature.\n"),
8306          PROMPT_CLEAR, 0 },
8307
8308        /* Journal inode is invalid */
8309        { PR_0_JOURNAL_BAD_INODE,
8310          N_("@S has an @n ext3 @j (@i %i).\n"),
8311          PROMPT_CLEAR, PR_PREEN_OK },
8312
8313        /* The external journal has (unsupported) multiple filesystems */
8314        { PR_0_JOURNAL_UNSUPP_MULTIFS,
8315          N_("External @j has multiple @f users (unsupported).\n"),
8316          PROMPT_NONE, PR_FATAL },
8317
8318        /* Can't find external journal */
8319        { PR_0_CANT_FIND_JOURNAL,
8320          N_("Can't find external @j\n"),
8321          PROMPT_NONE, PR_FATAL },
8322
8323        /* External journal has bad superblock */
8324        { PR_0_EXT_JOURNAL_BAD_SUPER,
8325          N_("External @j has bad @S\n"),
8326          PROMPT_NONE, PR_FATAL },
8327
8328        /* Superblock has a bad journal UUID */
8329        { PR_0_JOURNAL_BAD_UUID,
8330          N_("External @j does not support this @f\n"),
8331          PROMPT_NONE, PR_FATAL },
8332
8333        /* Journal has an unknown superblock type */
8334        { PR_0_JOURNAL_UNSUPP_SUPER,
8335          N_("Ext3 @j @S is unknown type %N (unsupported).\n"
8336             "It is likely that your copy of e2fsck is old and/or doesn't "
8337             "support this @j format.\n"
8338             "It is also possible the @j @S is corrupt.\n"),
8339          PROMPT_ABORT, PR_NO_OK | PR_AFTER_CODE, PR_0_JOURNAL_BAD_SUPER },
8340
8341        /* Journal superblock is corrupt */
8342        { PR_0_JOURNAL_BAD_SUPER,
8343          N_("Ext3 @j @S is corrupt.\n"),
8344          PROMPT_FIX, PR_PREEN_OK },
8345
8346        /* Superblock flag should be cleared */
8347        { PR_0_JOURNAL_HAS_JOURNAL,
8348          N_("@S doesn't have has_@j flag, but has ext3 @j %s.\n"),
8349          PROMPT_CLEAR, PR_PREEN_OK },
8350
8351        /* Superblock flag is incorrect */
8352        { PR_0_JOURNAL_RECOVER_SET,
8353          N_("@S has ext3 needs_recovery flag set, but no @j.\n"),
8354          PROMPT_CLEAR, PR_PREEN_OK },
8355
8356        /* Journal has data, but recovery flag is clear */
8357        { PR_0_JOURNAL_RECOVERY_CLEAR,
8358          N_("ext3 recovery flag is clear, but @j has data.\n"),
8359          PROMPT_NONE, 0 },
8360
8361        /* Ask if we should clear the journal */
8362        { PR_0_JOURNAL_RESET_JOURNAL,
8363          N_("Clear @j"),
8364          PROMPT_NULL, PR_PREEN_NOMSG },
8365
8366        /* Ask if we should run the journal anyway */
8367        { PR_0_JOURNAL_RUN,
8368          N_("Run @j anyway"),
8369          PROMPT_NULL, 0 },
8370
8371        /* Run the journal by default */
8372        { PR_0_JOURNAL_RUN_DEFAULT,
8373          N_("Recovery flag not set in backup @S, so running @j anyway.\n"),
8374          PROMPT_NONE, 0 },
8375
8376        /* Clearing orphan inode */
8377        { PR_0_ORPHAN_CLEAR_INODE,
8378          N_("%s @o @i %i (uid=%Iu, gid=%Ig, mode=%Im, size=%Is)\n"),
8379          PROMPT_NONE, 0 },
8380
8381        /* Illegal block found in orphaned inode */
8382        { PR_0_ORPHAN_ILLEGAL_BLOCK_NUM,
8383           N_("@I @b #%B (%b) found in @o @i %i.\n"),
8384          PROMPT_NONE, 0 },
8385
8386        /* Already cleared block found in orphaned inode */
8387        { PR_0_ORPHAN_ALREADY_CLEARED_BLOCK,
8388           N_("Already cleared @b #%B (%b) found in @o @i %i.\n"),
8389          PROMPT_NONE, 0 },
8390
8391        /* Illegal orphan inode in superblock */
8392        { PR_0_ORPHAN_ILLEGAL_HEAD_INODE,
8393          N_("@I @o @i %i in @S.\n"),
8394          PROMPT_NONE, 0 },
8395
8396        /* Illegal inode in orphaned inode list */
8397        { PR_0_ORPHAN_ILLEGAL_INODE,
8398          N_("@I @i %i in @o @i list.\n"),
8399          PROMPT_NONE, 0 },
8400
8401        /* Filesystem revision is 0, but feature flags are set */
8402        { PR_0_FS_REV_LEVEL,
8403          N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
8404          PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8405
8406        /* Journal superblock has an unknown read-only feature flag set */
8407        { PR_0_JOURNAL_UNSUPP_ROCOMPAT,
8408          N_("Ext3 @j @S has an unknown read-only feature flag set.\n"),
8409          PROMPT_ABORT, 0 },
8410
8411        /* Journal superblock has an unknown incompatible feature flag set */
8412        { PR_0_JOURNAL_UNSUPP_INCOMPAT,
8413          N_("Ext3 @j @S has an unknown incompatible feature flag set.\n"),
8414          PROMPT_ABORT, 0 },
8415
8416        /* Journal has unsupported version number */
8417        { PR_0_JOURNAL_UNSUPP_VERSION,
8418          N_("@j version not supported by this e2fsck.\n"),
8419          PROMPT_ABORT, 0 },
8420
8421        /* Moving journal to hidden file */
8422        { PR_0_MOVE_JOURNAL,
8423          N_("Moving @j from /%s to hidden @i.\n\n"),
8424          PROMPT_NONE, 0 },
8425
8426        /* Error moving journal to hidden file */
8427        { PR_0_ERR_MOVE_JOURNAL,
8428          N_("Error moving @j: %m\n\n"),
8429          PROMPT_NONE, 0 },
8430
8431        /* Clearing V2 journal superblock */
8432        { PR_0_CLEAR_V2_JOURNAL,
8433          N_("Found @n V2 @j @S fields (from V1 @j).\n"
8434             "Clearing fields beyond the V1 @j @S...\n\n"),
8435          PROMPT_NONE, 0 },
8436
8437        /* Backup journal inode blocks */
8438        { PR_0_BACKUP_JNL,
8439          N_("Backing up @j @i @b information.\n\n"),
8440          PROMPT_NONE, 0 },
8441
8442        /* Reserved blocks w/o resize_inode */
8443        { PR_0_NONZERO_RESERVED_GDT_BLOCKS,
8444          N_("@f does not have resize_@i enabled, but s_reserved_gdt_@bs\n"
8445             "is %N; @s zero.  "),
8446          PROMPT_FIX, 0 },
8447
8448        /* Resize_inode not enabled, but resize inode is non-zero */
8449        { PR_0_CLEAR_RESIZE_INODE,
8450          N_("Resize_@i not enabled, but the resize @i is non-zero.  "),
8451          PROMPT_CLEAR, 0 },
8452
8453        /* Resize inode invalid */
8454        { PR_0_RESIZE_INODE_INVALID,
8455          N_("Resize @i not valid.  "),
8456          PROMPT_RECREATE, 0 },
8457
8458        /* Pass 1 errors */
8459
8460        /* Pass 1: Checking inodes, blocks, and sizes */
8461        { PR_1_PASS_HEADER,
8462          N_("Pass 1: Checking @is, @bs, and sizes\n"),
8463          PROMPT_NONE, 0 },
8464
8465        /* Root directory is not an inode */
8466        { PR_1_ROOT_NO_DIR, N_("@r is not a @d.  "),
8467          PROMPT_CLEAR, 0 },
8468
8469        /* Root directory has dtime set */
8470        { PR_1_ROOT_DTIME,
8471          N_("@r has dtime set (probably due to old mke2fs).  "),
8472          PROMPT_FIX, PR_PREEN_OK },
8473
8474        /* Reserved inode has bad mode */
8475        { PR_1_RESERVED_BAD_MODE,
8476          N_("Reserved @i %i (%Q) has @n mode.  "),
8477          PROMPT_CLEAR, PR_PREEN_OK },
8478
8479        /* Deleted inode has zero dtime */
8480        { PR_1_ZERO_DTIME,
8481          N_("@D @i %i has zero dtime.  "),
8482          PROMPT_FIX, PR_PREEN_OK },
8483
8484        /* Inode in use, but dtime set */
8485        { PR_1_SET_DTIME,
8486          N_("@i %i is in use, but has dtime set.  "),
8487          PROMPT_FIX, PR_PREEN_OK },
8488
8489        /* Zero-length directory */
8490        { PR_1_ZERO_LENGTH_DIR,
8491          N_("@i %i is a @z @d.  "),
8492          PROMPT_CLEAR, PR_PREEN_OK },
8493
8494        /* Block bitmap conflicts with some other fs block */
8495        { PR_1_BB_CONFLICT,
8496          N_("@g %g's @b @B at %b @C.\n"),
8497          PROMPT_RELOCATE, 0 },
8498
8499        /* Inode bitmap conflicts with some other fs block */
8500        { PR_1_IB_CONFLICT,
8501          N_("@g %g's @i @B at %b @C.\n"),
8502          PROMPT_RELOCATE, 0 },
8503
8504        /* Inode table conflicts with some other fs block */
8505        { PR_1_ITABLE_CONFLICT,
8506          N_("@g %g's @i table at %b @C.\n"),
8507          PROMPT_RELOCATE, 0 },
8508
8509        /* Block bitmap is on a bad block */
8510        { PR_1_BB_BAD_BLOCK,
8511          N_("@g %g's @b @B (%b) is bad.  "),
8512          PROMPT_RELOCATE, 0 },
8513
8514        /* Inode bitmap is on a bad block */
8515        { PR_1_IB_BAD_BLOCK,
8516          N_("@g %g's @i @B (%b) is bad.  "),
8517          PROMPT_RELOCATE, 0 },
8518
8519        /* Inode has incorrect i_size */
8520        { PR_1_BAD_I_SIZE,
8521          N_("@i %i, i_size is %Is, @s %N.  "),
8522          PROMPT_FIX, PR_PREEN_OK },
8523
8524        /* Inode has incorrect i_blocks */
8525        { PR_1_BAD_I_BLOCKS,
8526          N_("@i %i, i_@bs is %Ib, @s %N.  "),
8527          PROMPT_FIX, PR_PREEN_OK },
8528
8529        /* Illegal blocknumber in inode */
8530        { PR_1_ILLEGAL_BLOCK_NUM,
8531          N_("@I @b #%B (%b) in @i %i.  "),
8532          PROMPT_CLEAR, PR_LATCH_BLOCK },
8533
8534        /* Block number overlaps fs metadata */
8535        { PR_1_BLOCK_OVERLAPS_METADATA,
8536          N_("@b #%B (%b) overlaps @f metadata in @i %i.  "),
8537          PROMPT_CLEAR, PR_LATCH_BLOCK },
8538
8539        /* Inode has illegal blocks (latch question) */
8540        { PR_1_INODE_BLOCK_LATCH,
8541          N_("@i %i has illegal @b(s).  "),
8542          PROMPT_CLEAR, 0 },
8543
8544        /* Too many bad blocks in inode */
8545        { PR_1_TOO_MANY_BAD_BLOCKS,
8546          N_("Too many illegal @bs in @i %i.\n"),
8547          PROMPT_CLEAR_INODE, PR_NO_OK },
8548
8549        /* Illegal block number in bad block inode */
8550        { PR_1_BB_ILLEGAL_BLOCK_NUM,
8551          N_("@I @b #%B (%b) in bad @b @i.  "),
8552          PROMPT_CLEAR, PR_LATCH_BBLOCK },
8553
8554        /* Bad block inode has illegal blocks (latch question) */
8555        { PR_1_INODE_BBLOCK_LATCH,
8556          N_("Bad @b @i has illegal @b(s).  "),
8557          PROMPT_CLEAR, 0 },
8558
8559        /* Duplicate or bad blocks in use! */
8560        { PR_1_DUP_BLOCKS_PREENSTOP,
8561          N_("Duplicate or bad @b in use!\n"),
8562          PROMPT_NONE, 0 },
8563
8564        /* Bad block used as bad block indirect block */
8565        { PR_1_BBINODE_BAD_METABLOCK,
8566          N_("Bad @b %b used as bad @b @i indirect @b.  "),
8567          PROMPT_CLEAR, PR_LATCH_BBLOCK },
8568
8569        /* Inconsistency can't be fixed prompt */
8570        { PR_1_BBINODE_BAD_METABLOCK_PROMPT,
8571          N_("\nThe bad @b @i has probably been corrupted.  You probably\n"
8572             "should stop now and run ""e2fsck -c"" to scan for bad blocks\n"
8573             "in the @f.\n"),
8574          PROMPT_CONTINUE, PR_PREEN_NOMSG },
8575
8576        /* Bad primary block */
8577        { PR_1_BAD_PRIMARY_BLOCK,
8578          N_("\nIf the @b is really bad, the @f cannot be fixed.\n"),
8579          PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK_PROMPT },
8580
8581        /* Bad primary block prompt */
8582        { PR_1_BAD_PRIMARY_BLOCK_PROMPT,
8583          N_("You can remove this @b from the bad @b list and hope\n"
8584             "that the @b is really OK.  But there are no guarantees.\n\n"),
8585          PROMPT_CLEAR, PR_PREEN_NOMSG },
8586
8587        /* Bad primary superblock */
8588        { PR_1_BAD_PRIMARY_SUPERBLOCK,
8589          N_("The primary @S (%b) is on the bad @b list.\n"),
8590          PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8591
8592        /* Bad primary block group descriptors */
8593        { PR_1_BAD_PRIMARY_GROUP_DESCRIPTOR,
8594          N_("Block %b in the primary @g descriptors "
8595          "is on the bad @b list\n"),
8596          PROMPT_NONE, PR_AFTER_CODE, PR_1_BAD_PRIMARY_BLOCK },
8597
8598        /* Bad superblock in group */
8599        { PR_1_BAD_SUPERBLOCK,
8600          N_("Warning: Group %g's @S (%b) is bad.\n"),
8601          PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8602
8603        /* Bad block group descriptors in group */
8604        { PR_1_BAD_GROUP_DESCRIPTORS,
8605          N_("Warning: Group %g's copy of the @g descriptors has a bad "
8606          "@b (%b).\n"),
8607          PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
8608
8609        /* Block claimed for no reason */
8610        { PR_1_PROGERR_CLAIMED_BLOCK,
8611          N_("Programming error?  @b #%b claimed for no reason in "
8612          "process_bad_@b.\n"),
8613          PROMPT_NONE, PR_PREEN_OK },
8614
8615        /* Error allocating blocks for relocating metadata */
8616        { PR_1_RELOC_BLOCK_ALLOCATE,
8617          N_("@A %N contiguous @b(s) in @b @g %g for %s: %m\n"),
8618          PROMPT_NONE, PR_PREEN_OK },
8619
8620        /* Error allocating block buffer during relocation process */
8621        { PR_1_RELOC_MEMORY_ALLOCATE,
8622          N_("@A @b buffer for relocating %s\n"),
8623          PROMPT_NONE, PR_PREEN_OK },
8624
8625        /* Relocating metadata group information from X to Y */
8626        { PR_1_RELOC_FROM_TO,
8627          N_("Relocating @g %g's %s from %b to %c...\n"),
8628          PROMPT_NONE, PR_PREEN_OK },
8629
8630        /* Relocating metatdata group information to X */
8631        { PR_1_RELOC_TO,
8632          N_("Relocating @g %g's %s to %c...\n"), /* xgettext:no-c-format */
8633          PROMPT_NONE, PR_PREEN_OK },
8634
8635        /* Block read error during relocation process */
8636        { PR_1_RELOC_READ_ERR,
8637          N_("Warning: could not read @b %b of %s: %m\n"),
8638          PROMPT_NONE, PR_PREEN_OK },
8639
8640        /* Block write error during relocation process */
8641        { PR_1_RELOC_WRITE_ERR,
8642          N_("Warning: could not write @b %b for %s: %m\n"),
8643          PROMPT_NONE, PR_PREEN_OK },
8644
8645        /* Error allocating inode bitmap */
8646        { PR_1_ALLOCATE_IBITMAP_ERROR,
8647          N_("@A @i @B (%N): %m\n"),
8648          PROMPT_NONE, PR_FATAL },
8649
8650        /* Error allocating block bitmap */
8651        { PR_1_ALLOCATE_BBITMAP_ERROR,
8652          N_("@A @b @B (%N): %m\n"),
8653          PROMPT_NONE, PR_FATAL },
8654
8655        /* Error allocating icount structure */
8656        { PR_1_ALLOCATE_ICOUNT,
8657          N_("@A icount link information: %m\n"),
8658          PROMPT_NONE, PR_FATAL },
8659
8660        /* Error allocating dbcount */
8661        { PR_1_ALLOCATE_DBCOUNT,
8662          N_("@A @d @b array: %m\n"),
8663          PROMPT_NONE, PR_FATAL },
8664
8665        /* Error while scanning inodes */
8666        { PR_1_ISCAN_ERROR,
8667          N_("Error while scanning @is (%i): %m\n"),
8668          PROMPT_NONE, PR_FATAL },
8669
8670        /* Error while iterating over blocks */
8671        { PR_1_BLOCK_ITERATE,
8672          N_("Error while iterating over @bs in @i %i: %m\n"),
8673          PROMPT_NONE, PR_FATAL },
8674
8675        /* Error while storing inode count information */
8676        { PR_1_ICOUNT_STORE,
8677          N_("Error storing @i count information (@i=%i, count=%N): %m\n"),
8678          PROMPT_NONE, PR_FATAL },
8679
8680        /* Error while storing directory block information */
8681        { PR_1_ADD_DBLOCK,
8682          N_("Error storing @d @b information "
8683          "(@i=%i, @b=%b, num=%N): %m\n"),
8684          PROMPT_NONE, PR_FATAL },
8685
8686        /* Error while reading inode (for clearing) */
8687        { PR_1_READ_INODE,
8688          N_("Error reading @i %i: %m\n"),
8689          PROMPT_NONE, PR_FATAL },
8690
8691        /* Suppress messages prompt */
8692        { PR_1_SUPPRESS_MESSAGES, "", PROMPT_SUPPRESS, PR_NO_OK },
8693
8694        /* Imagic flag set on an inode when filesystem doesn't support it */
8695        { PR_1_SET_IMAGIC,
8696          N_("@i %i has imagic flag set.  "),
8697          PROMPT_CLEAR, 0 },
8698
8699        /* Immutable flag set on a device or socket inode */
8700        { PR_1_SET_IMMUTABLE,
8701          N_("Special (@v/socket/fifo/symlink) file (@i %i) has immutable\n"
8702             "or append-only flag set.  "),
8703          PROMPT_CLEAR, PR_PREEN_OK | PR_PREEN_NO | PR_NO_OK },
8704
8705        /* Compression flag set on an inode when filesystem doesn't support it */
8706        { PR_1_COMPR_SET,
8707          N_("@i %i has @cion flag set on @f without @cion support.  "),
8708          PROMPT_CLEAR, 0 },
8709
8710        /* Non-zero size for device, fifo or socket inode */
8711        { PR_1_SET_NONZSIZE,
8712          N_("Special (@v/socket/fifo) @i %i has non-zero size.  "),
8713          PROMPT_FIX, PR_PREEN_OK },
8714
8715        /* Filesystem revision is 0, but feature flags are set */
8716        { PR_1_FS_REV_LEVEL,
8717          N_("@f has feature flag(s) set, but is a revision 0 @f.  "),
8718          PROMPT_FIX, PR_PREEN_OK | PR_NO_OK },
8719
8720        /* Journal inode is not in use, but contains data */
8721        { PR_1_JOURNAL_INODE_NOT_CLEAR,
8722          N_("@j @i is not in use, but contains data.  "),
8723          PROMPT_CLEAR, PR_PREEN_OK },
8724
8725        /* Journal has bad mode */
8726        { PR_1_JOURNAL_BAD_MODE,
8727          N_("@j is not regular file.  "),
8728          PROMPT_FIX, PR_PREEN_OK },
8729
8730        /* Deal with inodes that were part of orphan linked list */
8731        { PR_1_LOW_DTIME,
8732          N_("@i %i was part of the @o @i list.  "),
8733          PROMPT_FIX, PR_LATCH_LOW_DTIME, 0 },
8734
8735        /* Deal with inodes that were part of corrupted orphan linked
8736           list (latch question) */
8737        { PR_1_ORPHAN_LIST_REFUGEES,
8738          N_("@is that were part of a corrupted orphan linked list found.  "),
8739          PROMPT_FIX, 0 },
8740
8741        /* Error allocating refcount structure */
8742        { PR_1_ALLOCATE_REFCOUNT,
8743          N_("@A refcount structure (%N): %m\n"),
8744          PROMPT_NONE, PR_FATAL },
8745
8746        /* Error reading extended attribute block */
8747        { PR_1_READ_EA_BLOCK,
8748          N_("Error reading @a @b %b for @i %i.  "),
8749          PROMPT_CLEAR, 0 },
8750
8751        /* Invalid extended attribute block */
8752        { PR_1_BAD_EA_BLOCK,
8753          N_("@i %i has a bad @a @b %b.  "),
8754          PROMPT_CLEAR, 0 },
8755
8756        /* Error reading Extended Attribute block while fixing refcount */
8757        { PR_1_EXTATTR_READ_ABORT,
8758          N_("Error reading @a @b %b (%m).  "),
8759          PROMPT_ABORT, 0 },
8760
8761        /* Extended attribute reference count incorrect */
8762        { PR_1_EXTATTR_REFCOUNT,
8763          N_("@a @b %b has reference count %B, @s %N.  "),
8764          PROMPT_FIX, 0 },
8765
8766        /* Error writing Extended Attribute block while fixing refcount */
8767        { PR_1_EXTATTR_WRITE,
8768          N_("Error writing @a @b %b (%m).  "),
8769          PROMPT_ABORT, 0 },
8770
8771        /* Multiple EA blocks not supported */
8772        { PR_1_EA_MULTI_BLOCK,
8773          N_("@a @b %b has h_@bs > 1.  "),
8774          PROMPT_CLEAR, 0},
8775
8776        /* Error allocating EA region allocation structure */
8777        { PR_1_EA_ALLOC_REGION,
8778          N_("@A @a @b %b.  "),
8779          PROMPT_ABORT, 0},
8780
8781        /* Error EA allocation collision */
8782        { PR_1_EA_ALLOC_COLLISION,
8783          N_("@a @b %b is corrupt (allocation collision).  "),
8784          PROMPT_CLEAR, 0},
8785
8786        /* Bad extended attribute name */
8787        { PR_1_EA_BAD_NAME,
8788          N_("@a @b %b is corrupt (@n name).  "),
8789          PROMPT_CLEAR, 0},
8790
8791        /* Bad extended attribute value */
8792        { PR_1_EA_BAD_VALUE,
8793          N_("@a @b %b is corrupt (@n value).  "),
8794          PROMPT_CLEAR, 0},
8795
8796        /* Inode too big (latch question) */
8797        { PR_1_INODE_TOOBIG,
8798          N_("@i %i is too big.  "), PROMPT_TRUNCATE, 0 },
8799
8800        /* Directory too big */
8801        { PR_1_TOOBIG_DIR,
8802          N_("@b #%B (%b) causes @d to be too big.  "),
8803          PROMPT_CLEAR, PR_LATCH_TOOBIG },
8804
8805        /* Regular file too big */
8806        { PR_1_TOOBIG_REG,
8807          N_("@b #%B (%b) causes file to be too big.  "),
8808          PROMPT_CLEAR, PR_LATCH_TOOBIG },
8809
8810        /* Symlink too big */
8811        { PR_1_TOOBIG_SYMLINK,
8812          N_("@b #%B (%b) causes symlink to be too big.  "),
8813          PROMPT_CLEAR, PR_LATCH_TOOBIG },
8814
8815        /* INDEX_FL flag set on a non-HTREE filesystem */
8816        { PR_1_HTREE_SET,
8817          N_("@i %i has INDEX_FL flag set on @f without htree support.\n"),
8818          PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8819
8820        /* INDEX_FL flag set on a non-directory */
8821        { PR_1_HTREE_NODIR,
8822          N_("@i %i has INDEX_FL flag set but is not a @d.\n"),
8823          PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8824
8825        /* Invalid root node in HTREE directory */
8826        { PR_1_HTREE_BADROOT,
8827          N_("@h %i has an @n root node.\n"),
8828          PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8829
8830        /* Unsupported hash version in HTREE directory */
8831        { PR_1_HTREE_HASHV,
8832          N_("@h %i has an unsupported hash version (%N)\n"),
8833          PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8834
8835        /* Incompatible flag in HTREE root node */
8836        { PR_1_HTREE_INCOMPAT,
8837          N_("@h %i uses an incompatible htree root node flag.\n"),
8838          PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8839
8840        /* HTREE too deep */
8841        { PR_1_HTREE_DEPTH,
8842          N_("@h %i has a tree depth (%N) which is too big\n"),
8843          PROMPT_CLEAR_HTREE, PR_PREEN_OK },
8844
8845        /* Bad block has indirect block that conflicts with filesystem block */
8846        { PR_1_BB_FS_BLOCK,
8847          N_("Bad @b @i has an indirect @b (%b) that conflicts with\n"
8848             "@f metadata.  "),
8849          PROMPT_CLEAR, PR_LATCH_BBLOCK },
8850
8851        /* Resize inode failed */
8852        { PR_1_RESIZE_INODE_CREATE,
8853          N_("Resize @i (re)creation failed: %m."),
8854          PROMPT_ABORT, 0 },
8855
8856        /* invalid inode->i_extra_isize */
8857        { PR_1_EXTRA_ISIZE,
8858          N_("@i %i has a extra size (%IS) which is @n\n"),
8859          PROMPT_FIX, PR_PREEN_OK },
8860
8861        /* invalid ea entry->e_name_len */
8862        { PR_1_ATTR_NAME_LEN,
8863          N_("@a in @i %i has a namelen (%N) which is @n\n"),
8864          PROMPT_CLEAR, PR_PREEN_OK },
8865
8866        /* invalid ea entry->e_value_size */
8867        { PR_1_ATTR_VALUE_SIZE,
8868          N_("@a in @i %i has a value size (%N) which is @n\n"),
8869          PROMPT_CLEAR, PR_PREEN_OK },
8870
8871        /* invalid ea entry->e_value_offs */
8872        { PR_1_ATTR_VALUE_OFFSET,
8873          N_("@a in @i %i has a value offset (%N) which is @n\n"),
8874          PROMPT_CLEAR, PR_PREEN_OK },
8875
8876        /* invalid ea entry->e_value_block */
8877        { PR_1_ATTR_VALUE_BLOCK,
8878          N_("@a in @i %i has a value @b (%N) which is @n (must be 0)\n"),
8879          PROMPT_CLEAR, PR_PREEN_OK },
8880
8881        /* invalid ea entry->e_hash */
8882        { PR_1_ATTR_HASH,
8883          N_("@a in @i %i has a hash (%N) which is @n (must be 0)\n"),
8884          PROMPT_CLEAR, PR_PREEN_OK },
8885
8886        /* Pass 1b errors */
8887
8888        /* Pass 1B: Rescan for duplicate/bad blocks */
8889        { PR_1B_PASS_HEADER,
8890          N_("\nRunning additional passes to resolve @bs claimed by more than one @i...\n"
8891          "Pass 1B: Rescanning for @m @bs\n"),
8892          PROMPT_NONE, 0 },
8893
8894        /* Duplicate/bad block(s) header */
8895        { PR_1B_DUP_BLOCK_HEADER,
8896          N_("@m @b(s) in @i %i:"),
8897          PROMPT_NONE, 0 },
8898
8899        /* Duplicate/bad block(s) in inode */
8900        { PR_1B_DUP_BLOCK,
8901          " %b",
8902          PROMPT_NONE, PR_LATCH_DBLOCK | PR_PREEN_NOHDR },
8903
8904        /* Duplicate/bad block(s) end */
8905        { PR_1B_DUP_BLOCK_END,
8906          "\n",
8907          PROMPT_NONE, PR_PREEN_NOHDR },
8908
8909        /* Error while scanning inodes */
8910        { PR_1B_ISCAN_ERROR,
8911          N_("Error while scanning inodes (%i): %m\n"),
8912          PROMPT_NONE, PR_FATAL },
8913
8914        /* Error allocating inode bitmap */
8915        { PR_1B_ALLOCATE_IBITMAP_ERROR,
8916          N_("@A @i @B (@i_dup_map): %m\n"),
8917          PROMPT_NONE, PR_FATAL },
8918
8919        /* Error while iterating over blocks */
8920        { PR_1B_BLOCK_ITERATE,
8921          N_("Error while iterating over @bs in @i %i (%s): %m\n"),
8922          PROMPT_NONE, 0 },
8923
8924        /* Error adjusting EA refcount */
8925        { PR_1B_ADJ_EA_REFCOUNT,
8926          N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
8927          PROMPT_NONE, 0 },
8928
8929
8930        /* Pass 1C: Scan directories for inodes with multiply-claimed blocks. */
8931        { PR_1C_PASS_HEADER,
8932          N_("Pass 1C: Scanning directories for @is with @m @bs.\n"),
8933          PROMPT_NONE, 0 },
8934
8935
8936        /* Pass 1D: Reconciling multiply-claimed blocks */
8937        { PR_1D_PASS_HEADER,
8938          N_("Pass 1D: Reconciling @m @bs\n"),
8939          PROMPT_NONE, 0 },
8940
8941        /* File has duplicate blocks */
8942        { PR_1D_DUP_FILE,
8943          N_("File %Q (@i #%i, mod time %IM)\n"
8944          "  has %B @m @b(s), shared with %N file(s):\n"),
8945          PROMPT_NONE, 0 },
8946
8947        /* List of files sharing duplicate blocks */
8948        { PR_1D_DUP_FILE_LIST,
8949          N_("\t%Q (@i #%i, mod time %IM)\n"),
8950          PROMPT_NONE, 0 },
8951
8952        /* File sharing blocks with filesystem metadata  */
8953        { PR_1D_SHARE_METADATA,
8954          N_("\t<@f metadata>\n"),
8955          PROMPT_NONE, 0 },
8956
8957        /* Report of how many duplicate/bad inodes */
8958        { PR_1D_NUM_DUP_INODES,
8959          N_("(There are %N @is containing @m @bs.)\n\n"),
8960          PROMPT_NONE, 0 },
8961
8962        /* Duplicated blocks already reassigned or cloned. */
8963        { PR_1D_DUP_BLOCKS_DEALT,
8964          N_("@m @bs already reassigned or cloned.\n\n"),
8965          PROMPT_NONE, 0 },
8966
8967        /* Clone duplicate/bad blocks? */
8968        { PR_1D_CLONE_QUESTION,
8969          "", PROMPT_CLONE, PR_NO_OK },
8970
8971        /* Delete file? */
8972        { PR_1D_DELETE_QUESTION,
8973          "", PROMPT_DELETE, 0 },
8974
8975        /* Couldn't clone file (error) */
8976        { PR_1D_CLONE_ERROR,
8977          N_("Couldn't clone file: %m\n"), PROMPT_NONE, 0 },
8978
8979        /* Pass 2 errors */
8980
8981        /* Pass 2: Checking directory structure */
8982        { PR_2_PASS_HEADER,
8983          N_("Pass 2: Checking @d structure\n"),
8984          PROMPT_NONE, 0 },
8985
8986        /* Bad inode number for '.' */
8987        { PR_2_BAD_INODE_DOT,
8988          N_("@n @i number for '.' in @d @i %i.\n"),
8989          PROMPT_FIX, 0 },
8990
8991        /* Directory entry has bad inode number */
8992        { PR_2_BAD_INO,
8993          N_("@E has @n @i #: %Di.\n"),
8994          PROMPT_CLEAR, 0 },
8995
8996        /* Directory entry has deleted or unused inode */
8997        { PR_2_UNUSED_INODE,
8998          N_("@E has @D/unused @i %Di.  "),
8999          PROMPT_CLEAR, PR_PREEN_OK },
9000
9001        /* Directry entry is link to '.' */
9002        { PR_2_LINK_DOT,
9003          N_("@E @L to '.'  "),
9004          PROMPT_CLEAR, 0 },
9005
9006        /* Directory entry points to inode now located in a bad block */
9007        { PR_2_BB_INODE,
9008          N_("@E points to @i (%Di) located in a bad @b.\n"),
9009          PROMPT_CLEAR, 0 },
9010
9011        /* Directory entry contains a link to a directory */
9012        { PR_2_LINK_DIR,
9013          N_("@E @L to @d %P (%Di).\n"),
9014          PROMPT_CLEAR, 0 },
9015
9016        /* Directory entry contains a link to the root directry */
9017        { PR_2_LINK_ROOT,
9018          N_("@E @L to the @r.\n"),
9019          PROMPT_CLEAR, 0 },
9020
9021        /* Directory entry has illegal characters in its name */
9022        { PR_2_BAD_NAME,
9023          N_("@E has illegal characters in its name.\n"),
9024          PROMPT_FIX, 0 },
9025
9026        /* Missing '.' in directory inode */
9027        { PR_2_MISSING_DOT,
9028          N_("Missing '.' in @d @i %i.\n"),
9029          PROMPT_FIX, 0 },
9030
9031        /* Missing '..' in directory inode */
9032        { PR_2_MISSING_DOT_DOT,
9033          N_("Missing '..' in @d @i %i.\n"),
9034          PROMPT_FIX, 0 },
9035
9036        /* First entry in directory inode doesn't contain '.' */
9037        { PR_2_1ST_NOT_DOT,
9038          N_("First @e '%Dn' (@i=%Di) in @d @i %i (%p) @s '.'\n"),
9039          PROMPT_FIX, 0 },
9040
9041        /* Second entry in directory inode doesn't contain '..' */
9042        { PR_2_2ND_NOT_DOT_DOT,
9043          N_("Second @e '%Dn' (@i=%Di) in @d @i %i @s '..'\n"),
9044          PROMPT_FIX, 0 },
9045
9046        /* i_faddr should be zero */
9047        { PR_2_FADDR_ZERO,
9048          N_("i_faddr @F %IF, @s zero.\n"),
9049          PROMPT_CLEAR, 0 },
9050
9051        /* i_file_acl should be zero */
9052        { PR_2_FILE_ACL_ZERO,
9053          N_("i_file_acl @F %If, @s zero.\n"),
9054          PROMPT_CLEAR, 0 },
9055
9056        /* i_dir_acl should be zero */
9057        { PR_2_DIR_ACL_ZERO,
9058          N_("i_dir_acl @F %Id, @s zero.\n"),
9059          PROMPT_CLEAR, 0 },
9060
9061        /* i_frag should be zero */
9062        { PR_2_FRAG_ZERO,
9063          N_("i_frag @F %N, @s zero.\n"),
9064          PROMPT_CLEAR, 0 },
9065
9066        /* i_fsize should be zero */
9067        { PR_2_FSIZE_ZERO,
9068          N_("i_fsize @F %N, @s zero.\n"),
9069          PROMPT_CLEAR, 0 },
9070
9071        /* inode has bad mode */
9072        { PR_2_BAD_MODE,
9073          N_("@i %i (%Q) has @n mode (%Im).\n"),
9074          PROMPT_CLEAR, 0 },
9075
9076        /* directory corrupted */
9077        { PR_2_DIR_CORRUPTED,
9078          N_("@d @i %i, @b %B, offset %N: @d corrupted\n"),
9079          PROMPT_SALVAGE, 0 },
9080
9081        /* filename too long */
9082        { PR_2_FILENAME_LONG,
9083          N_("@d @i %i, @b %B, offset %N: filename too long\n"),
9084          PROMPT_TRUNCATE, 0 },
9085
9086        /* Directory inode has a missing block (hole) */
9087        { PR_2_DIRECTORY_HOLE,
9088          N_("@d @i %i has an unallocated @b #%B.  "),
9089          PROMPT_ALLOCATE, 0 },
9090
9091        /* '.' is not NULL terminated */
9092        { PR_2_DOT_NULL_TERM,
9093          N_("'.' @d @e in @d @i %i is not NULL terminated\n"),
9094          PROMPT_FIX, 0 },
9095
9096        /* '..' is not NULL terminated */
9097        { PR_2_DOT_DOT_NULL_TERM,
9098          N_("'..' @d @e in @d @i %i is not NULL terminated\n"),
9099          PROMPT_FIX, 0 },
9100
9101        /* Illegal character device inode */
9102        { PR_2_BAD_CHAR_DEV,
9103          N_("@i %i (%Q) is an @I character @v.\n"),
9104          PROMPT_CLEAR, 0 },
9105
9106        /* Illegal block device inode */
9107        { PR_2_BAD_BLOCK_DEV,
9108          N_("@i %i (%Q) is an @I @b @v.\n"),
9109          PROMPT_CLEAR, 0 },
9110
9111        /* Duplicate '.' entry */
9112        { PR_2_DUP_DOT,
9113          N_("@E is duplicate '.' @e.\n"),
9114          PROMPT_FIX, 0 },
9115
9116        /* Duplicate '..' entry */
9117        { PR_2_DUP_DOT_DOT,
9118          N_("@E is duplicate '..' @e.\n"),
9119          PROMPT_FIX, 0 },
9120
9121        /* Internal error: couldn't find dir_info */
9122        { PR_2_NO_DIRINFO,
9123          N_("Internal error: cannot find dir_info for %i.\n"),
9124          PROMPT_NONE, PR_FATAL },
9125
9126        /* Final rec_len is wrong */
9127        { PR_2_FINAL_RECLEN,
9128          N_("@E has rec_len of %Dr, @s %N.\n"),
9129          PROMPT_FIX, 0 },
9130
9131        /* Error allocating icount structure */
9132        { PR_2_ALLOCATE_ICOUNT,
9133          N_("@A icount structure: %m\n"),
9134          PROMPT_NONE, PR_FATAL },
9135
9136        /* Error iterating over directory blocks */
9137        { PR_2_DBLIST_ITERATE,
9138          N_("Error iterating over @d @bs: %m\n"),
9139          PROMPT_NONE, PR_FATAL },
9140
9141        /* Error reading directory block */
9142        { PR_2_READ_DIRBLOCK,
9143          N_("Error reading @d @b %b (@i %i): %m\n"),
9144          PROMPT_CONTINUE, 0 },
9145
9146        /* Error writing directory block */
9147        { PR_2_WRITE_DIRBLOCK,
9148          N_("Error writing @d @b %b (@i %i): %m\n"),
9149          PROMPT_CONTINUE, 0 },
9150
9151        /* Error allocating new directory block */
9152        { PR_2_ALLOC_DIRBOCK,
9153          N_("@A new @d @b for @i %i (%s): %m\n"),
9154          PROMPT_NONE, 0 },
9155
9156        /* Error deallocating inode */
9157        { PR_2_DEALLOC_INODE,
9158          N_("Error deallocating @i %i: %m\n"),
9159          PROMPT_NONE, PR_FATAL },
9160
9161        /* Directory entry for '.' is big.  Split? */
9162        { PR_2_SPLIT_DOT,
9163          N_("@d @e for '.' is big.  "),
9164          PROMPT_SPLIT, PR_NO_OK },
9165
9166        /* Illegal FIFO inode */
9167        { PR_2_BAD_FIFO,
9168          N_("@i %i (%Q) is an @I FIFO.\n"),
9169          PROMPT_CLEAR, 0 },
9170
9171        /* Illegal socket inode */
9172        { PR_2_BAD_SOCKET,
9173          N_("@i %i (%Q) is an @I socket.\n"),
9174          PROMPT_CLEAR, 0 },
9175
9176        /* Directory filetype not set */
9177        { PR_2_SET_FILETYPE,
9178          N_("Setting filetype for @E to %N.\n"),
9179          PROMPT_NONE, PR_PREEN_OK | PR_NO_OK | PR_NO_NOMSG },
9180
9181        /* Directory filetype incorrect */
9182        { PR_2_BAD_FILETYPE,
9183          N_("@E has an incorrect filetype (was %Dt, @s %N).\n"),
9184          PROMPT_FIX, 0 },
9185
9186        /* Directory filetype set on filesystem */
9187        { PR_2_CLEAR_FILETYPE,
9188          N_("@E has filetype set.\n"),
9189          PROMPT_CLEAR, PR_PREEN_OK },
9190
9191        /* Directory filename is null */
9192        { PR_2_NULL_NAME,
9193          N_("@E has a @z name.\n"),
9194          PROMPT_CLEAR, 0 },
9195
9196        /* Invalid symlink */
9197        { PR_2_INVALID_SYMLINK,
9198          N_("Symlink %Q (@i #%i) is @n.\n"),
9199          PROMPT_CLEAR, 0 },
9200
9201        /* i_file_acl (extended attribute block) is bad */
9202        { PR_2_FILE_ACL_BAD,
9203          N_("@a @b @F @n (%If).\n"),
9204          PROMPT_CLEAR, 0 },
9205
9206        /* Filesystem contains large files, but has no such flag in sb */
9207        { PR_2_FEATURE_LARGE_FILES,
9208          N_("@f contains large files, but lacks LARGE_FILE flag in @S.\n"),
9209          PROMPT_FIX, 0 },
9210
9211        /* Node in HTREE directory not referenced */
9212        { PR_2_HTREE_NOTREF,
9213          N_("@p @h %d: node (%B) not referenced\n"),
9214          PROMPT_NONE, 0 },
9215
9216        /* Node in HTREE directory referenced twice */
9217        { PR_2_HTREE_DUPREF,
9218          N_("@p @h %d: node (%B) referenced twice\n"),
9219          PROMPT_NONE, 0 },
9220
9221        /* Node in HTREE directory has bad min hash */
9222        { PR_2_HTREE_MIN_HASH,
9223          N_("@p @h %d: node (%B) has bad min hash\n"),
9224          PROMPT_NONE, 0 },
9225
9226        /* Node in HTREE directory has bad max hash */
9227        { PR_2_HTREE_MAX_HASH,
9228          N_("@p @h %d: node (%B) has bad max hash\n"),
9229          PROMPT_NONE, 0 },
9230
9231        /* Clear invalid HTREE directory */
9232        { PR_2_HTREE_CLEAR,
9233          N_("@n @h %d (%q).  "), PROMPT_CLEAR, 0 },
9234
9235        /* Bad block in htree interior node */
9236        { PR_2_HTREE_BADBLK,
9237          N_("@p @h %d (%q): bad @b number %b.\n"),
9238          PROMPT_CLEAR_HTREE, 0 },
9239
9240        /* Error adjusting EA refcount */
9241        { PR_2_ADJ_EA_REFCOUNT,
9242          N_("Error adjusting refcount for @a @b %b (@i %i): %m\n"),
9243          PROMPT_NONE, PR_FATAL },
9244
9245        /* Invalid HTREE root node */
9246        { PR_2_HTREE_BAD_ROOT,
9247          N_("@p @h %d: root node is @n\n"),
9248          PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9249
9250        /* Invalid HTREE limit */
9251        { PR_2_HTREE_BAD_LIMIT,
9252          N_("@p @h %d: node (%B) has @n limit (%N)\n"),
9253          PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9254
9255        /* Invalid HTREE count */
9256        { PR_2_HTREE_BAD_COUNT,
9257          N_("@p @h %d: node (%B) has @n count (%N)\n"),
9258          PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9259
9260        /* HTREE interior node has out-of-order hashes in table */
9261        { PR_2_HTREE_HASH_ORDER,
9262          N_("@p @h %d: node (%B) has an unordered hash table\n"),
9263          PROMPT_CLEAR_HTREE, PR_PREEN_OK },
9264
9265        /* Node in HTREE directory has invalid depth */
9266        { PR_2_HTREE_BAD_DEPTH,
9267          N_("@p @h %d: node (%B) has @n depth\n"),
9268          PROMPT_NONE, 0 },
9269
9270        /* Duplicate directory entry found */
9271        { PR_2_DUPLICATE_DIRENT,
9272          N_("Duplicate @E found.  "),
9273          PROMPT_CLEAR, 0 },
9274
9275        /* Non-unique filename found */
9276        { PR_2_NON_UNIQUE_FILE, /* xgettext: no-c-format */
9277          N_("@E has a non-unique filename.\nRename to %s"),
9278          PROMPT_NULL, 0 },
9279
9280        /* Duplicate directory entry found */
9281        { PR_2_REPORT_DUP_DIRENT,
9282          N_("Duplicate @e '%Dn' found.\n\tMarking %p (%i) to be rebuilt.\n\n"),
9283          PROMPT_NONE, 0 },
9284
9285        /* Pass 3 errors */
9286
9287        /* Pass 3: Checking directory connectivity */
9288        { PR_3_PASS_HEADER,
9289          N_("Pass 3: Checking @d connectivity\n"),
9290          PROMPT_NONE, 0 },
9291
9292        /* Root inode not allocated */
9293        { PR_3_NO_ROOT_INODE,
9294          N_("@r not allocated.  "),
9295          PROMPT_ALLOCATE, 0 },
9296
9297        /* No room in lost+found */
9298        { PR_3_EXPAND_LF_DIR,
9299          N_("No room in @l @d.  "),
9300          PROMPT_EXPAND, 0 },
9301
9302        /* Unconnected directory inode */
9303        { PR_3_UNCONNECTED_DIR,
9304          N_("Unconnected @d @i %i (%p)\n"),
9305          PROMPT_CONNECT, 0 },
9306
9307        /* /lost+found not found */
9308        { PR_3_NO_LF_DIR,
9309          N_("/@l not found.  "),
9310          PROMPT_CREATE, PR_PREEN_OK },
9311
9312        /* .. entry is incorrect */
9313        { PR_3_BAD_DOT_DOT,
9314          N_("'..' in %Q (%i) is %P (%j), @s %q (%d).\n"),
9315          PROMPT_FIX, 0 },
9316
9317        /* Bad or non-existent /lost+found.  Cannot reconnect */
9318        { PR_3_NO_LPF,
9319          N_("Bad or non-existent /@l.  Cannot reconnect.\n"),
9320          PROMPT_NONE, 0 },
9321
9322        /* Could not expand /lost+found */
9323        { PR_3_CANT_EXPAND_LPF,
9324          N_("Could not expand /@l: %m\n"),
9325          PROMPT_NONE, 0 },
9326
9327        /* Could not reconnect inode */
9328        { PR_3_CANT_RECONNECT,
9329          N_("Could not reconnect %i: %m\n"),
9330          PROMPT_NONE, 0 },
9331
9332        /* Error while trying to find /lost+found */
9333        { PR_3_ERR_FIND_LPF,
9334          N_("Error while trying to find /@l: %m\n"),
9335          PROMPT_NONE, 0 },
9336
9337        /* Error in ext2fs_new_block while creating /lost+found */
9338        { PR_3_ERR_LPF_NEW_BLOCK,
9339          N_("ext2fs_new_@b: %m while trying to create /@l @d\n"),
9340          PROMPT_NONE, 0 },
9341
9342        /* Error in ext2fs_new_inode while creating /lost+found */
9343        { PR_3_ERR_LPF_NEW_INODE,
9344          N_("ext2fs_new_@i: %m while trying to create /@l @d\n"),
9345          PROMPT_NONE, 0 },
9346
9347        /* Error in ext2fs_new_dir_block while creating /lost+found */
9348        { PR_3_ERR_LPF_NEW_DIR_BLOCK,
9349          N_("ext2fs_new_dir_@b: %m while creating new @d @b\n"),
9350          PROMPT_NONE, 0 },
9351
9352        /* Error while writing directory block for /lost+found */
9353        { PR_3_ERR_LPF_WRITE_BLOCK,
9354          N_("ext2fs_write_dir_@b: %m while writing the @d @b for /@l\n"),
9355          PROMPT_NONE, 0 },
9356
9357        /* Error while adjusting inode count */
9358        { PR_3_ADJUST_INODE,
9359          N_("Error while adjusting @i count on @i %i\n"),
9360          PROMPT_NONE, 0 },
9361
9362        /* Couldn't fix parent directory -- error */
9363        { PR_3_FIX_PARENT_ERR,
9364          N_("Couldn't fix parent of @i %i: %m\n\n"),
9365          PROMPT_NONE, 0 },
9366
9367        /* Couldn't fix parent directory -- couldn't find it */
9368        { PR_3_FIX_PARENT_NOFIND,
9369          N_("Couldn't fix parent of @i %i: Couldn't find parent @d @e\n\n"),
9370          PROMPT_NONE, 0 },
9371
9372        /* Error allocating inode bitmap */
9373        { PR_3_ALLOCATE_IBITMAP_ERROR,
9374          N_("@A @i @B (%N): %m\n"),
9375          PROMPT_NONE, PR_FATAL },
9376
9377        /* Error creating root directory */
9378        { PR_3_CREATE_ROOT_ERROR,
9379          N_("Error creating root @d (%s): %m\n"),
9380          PROMPT_NONE, PR_FATAL },
9381
9382        /* Error creating lost and found directory */
9383        { PR_3_CREATE_LPF_ERROR,
9384          N_("Error creating /@l @d (%s): %m\n"),
9385          PROMPT_NONE, PR_FATAL },
9386
9387        /* Root inode is not directory; aborting */
9388        { PR_3_ROOT_NOT_DIR_ABORT,
9389          N_("@r is not a @d; aborting.\n"),
9390          PROMPT_NONE, PR_FATAL },
9391
9392        /* Cannot proceed without a root inode. */
9393        { PR_3_NO_ROOT_INODE_ABORT,
9394          N_("can't proceed without a @r.\n"),
9395          PROMPT_NONE, PR_FATAL },
9396
9397        /* Internal error: couldn't find dir_info */
9398        { PR_3_NO_DIRINFO,
9399          N_("Internal error: cannot find dir_info for %i.\n"),
9400          PROMPT_NONE, PR_FATAL },
9401
9402        /* Lost+found not a directory */
9403        { PR_3_LPF_NOTDIR,
9404          N_("/@l is not a @d (ino=%i)\n"),
9405          PROMPT_UNLINK, 0 },
9406
9407        /* Pass 3A Directory Optimization       */
9408
9409        /* Pass 3A: Optimizing directories */
9410        { PR_3A_PASS_HEADER,
9411          N_("Pass 3A: Optimizing directories\n"),
9412          PROMPT_NONE, PR_PREEN_NOMSG },
9413
9414        /* Error iterating over directories */
9415        { PR_3A_OPTIMIZE_ITER,
9416          N_("Failed to create dirs_to_hash iterator: %m"),
9417          PROMPT_NONE, 0 },
9418
9419        /* Error rehash directory */
9420        { PR_3A_OPTIMIZE_DIR_ERR,
9421          N_("Failed to optimize directory %q (%d): %m"),
9422          PROMPT_NONE, 0 },
9423
9424        /* Rehashing dir header */
9425        { PR_3A_OPTIMIZE_DIR_HEADER,
9426          N_("Optimizing directories: "),
9427          PROMPT_NONE, PR_MSG_ONLY },
9428
9429        /* Rehashing directory %d */
9430        { PR_3A_OPTIMIZE_DIR,
9431          " %d",
9432          PROMPT_NONE, PR_LATCH_OPTIMIZE_DIR | PR_PREEN_NOHDR},
9433
9434        /* Rehashing dir end */
9435        { PR_3A_OPTIMIZE_DIR_END,
9436          "\n",
9437          PROMPT_NONE, PR_PREEN_NOHDR },
9438
9439        /* Pass 4 errors */
9440
9441        /* Pass 4: Checking reference counts */
9442        { PR_4_PASS_HEADER,
9443          N_("Pass 4: Checking reference counts\n"),
9444          PROMPT_NONE, 0 },
9445
9446        /* Unattached zero-length inode */
9447        { PR_4_ZERO_LEN_INODE,
9448          N_("@u @z @i %i.  "),
9449          PROMPT_CLEAR, PR_PREEN_OK|PR_NO_OK },
9450
9451        /* Unattached inode */
9452        { PR_4_UNATTACHED_INODE,
9453          N_("@u @i %i\n"),
9454          PROMPT_CONNECT, 0 },
9455
9456        /* Inode ref count wrong */
9457        { PR_4_BAD_REF_COUNT,
9458          N_("@i %i ref count is %Il, @s %N.  "),
9459          PROMPT_FIX, PR_PREEN_OK },
9460
9461        { PR_4_INCONSISTENT_COUNT,
9462          N_("WARNING: PROGRAMMING BUG IN E2FSCK!\n"
9463          "\tOR SOME BONEHEAD (YOU) IS CHECKING A MOUNTED (LIVE) FILESYSTEM.\n"
9464          "@i_link_info[%i] is %N, @i.i_links_count is %Il.  "
9465          "They @s the same!\n"),
9466          PROMPT_NONE, 0 },
9467
9468        /* Pass 5 errors */
9469
9470        /* Pass 5: Checking group summary information */
9471        { PR_5_PASS_HEADER,
9472          N_("Pass 5: Checking @g summary information\n"),
9473          PROMPT_NONE, 0 },
9474
9475        /* Padding at end of inode bitmap is not set. */
9476        { PR_5_INODE_BMAP_PADDING,
9477          N_("Padding at end of @i @B is not set. "),
9478          PROMPT_FIX, PR_PREEN_OK },
9479
9480        /* Padding at end of block bitmap is not set. */
9481        { PR_5_BLOCK_BMAP_PADDING,
9482          N_("Padding at end of @b @B is not set. "),
9483          PROMPT_FIX, PR_PREEN_OK },
9484
9485        /* Block bitmap differences header */
9486        { PR_5_BLOCK_BITMAP_HEADER,
9487          N_("@b @B differences: "),
9488          PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG},
9489
9490        /* Block not used, but marked in bitmap */
9491        { PR_5_BLOCK_UNUSED,
9492          " -%b",
9493          PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9494
9495        /* Block used, but not marked used in bitmap */
9496        { PR_5_BLOCK_USED,
9497          " +%b",
9498          PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9499
9500        /* Block bitmap differences end */
9501        { PR_5_BLOCK_BITMAP_END,
9502          "\n",
9503          PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9504
9505        /* Inode bitmap differences header */
9506        { PR_5_INODE_BITMAP_HEADER,
9507          N_("@i @B differences: "),
9508          PROMPT_NONE, PR_PREEN_OK | PR_PREEN_NOMSG },
9509
9510        /* Inode not used, but marked in bitmap */
9511        { PR_5_INODE_UNUSED,
9512          " -%i",
9513          PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9514
9515        /* Inode used, but not marked used in bitmap */
9516        { PR_5_INODE_USED,
9517          " +%i",
9518          PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9519
9520        /* Inode bitmap differences end */
9521        { PR_5_INODE_BITMAP_END,
9522          "\n",
9523          PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9524
9525        /* Free inodes count for group wrong */
9526        { PR_5_FREE_INODE_COUNT_GROUP,
9527          N_("Free @is count wrong for @g #%g (%i, counted=%j).\n"),
9528          PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9529
9530        /* Directories count for group wrong */
9531        { PR_5_FREE_DIR_COUNT_GROUP,
9532          N_("Directories count wrong for @g #%g (%i, counted=%j).\n"),
9533          PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9534
9535        /* Free inodes count wrong */
9536        { PR_5_FREE_INODE_COUNT,
9537          N_("Free @is count wrong (%i, counted=%j).\n"),
9538          PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9539
9540        /* Free blocks count for group wrong */
9541        { PR_5_FREE_BLOCK_COUNT_GROUP,
9542          N_("Free @bs count wrong for @g #%g (%b, counted=%c).\n"),
9543          PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9544
9545        /* Free blocks count wrong */
9546        { PR_5_FREE_BLOCK_COUNT,
9547          N_("Free @bs count wrong (%b, counted=%c).\n"),
9548          PROMPT_FIX, PR_PREEN_OK | PR_PREEN_NOMSG },
9549
9550        /* Programming error: bitmap endpoints don't match */
9551        { PR_5_BMAP_ENDPOINTS,
9552          N_("PROGRAMMING ERROR: @f (#%N) @B endpoints (%b, %c) don't "
9553          "match calculated @B endpoints (%i, %j)\n"),
9554          PROMPT_NONE, PR_FATAL },
9555
9556        /* Internal error: fudging end of bitmap */
9557        { PR_5_FUDGE_BITMAP_ERROR,
9558          N_("Internal error: fudging end of bitmap (%N)\n"),
9559          PROMPT_NONE, PR_FATAL },
9560
9561        /* Error copying in replacement inode bitmap */
9562        { PR_5_COPY_IBITMAP_ERROR,
9563          N_("Error copying in replacement @i @B: %m\n"),
9564          PROMPT_NONE, PR_FATAL },
9565
9566        /* Error copying in replacement block bitmap */
9567        { PR_5_COPY_BBITMAP_ERROR,
9568          N_("Error copying in replacement @b @B: %m\n"),
9569          PROMPT_NONE, PR_FATAL },
9570
9571        /* Block range not used, but marked in bitmap */
9572        { PR_5_BLOCK_RANGE_UNUSED,
9573          " -(%b--%c)",
9574          PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9575
9576        /* Block range used, but not marked used in bitmap */
9577        { PR_5_BLOCK_RANGE_USED,
9578          " +(%b--%c)",
9579          PROMPT_NONE, PR_LATCH_BBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9580
9581        /* Inode range not used, but marked in bitmap */
9582        { PR_5_INODE_RANGE_UNUSED,
9583          " -(%i--%j)",
9584          PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9585
9586        /* Inode range used, but not marked used in bitmap */
9587        { PR_5_INODE_RANGE_USED,
9588          " +(%i--%j)",
9589          PROMPT_NONE, PR_LATCH_IBITMAP | PR_PREEN_OK | PR_PREEN_NOMSG },
9590
9591        { 0 }
9592};
9593
9594/*
9595 * This is the latch flags register.  It allows several problems to be
9596 * "latched" together.  This means that the user has to answer but one
9597 * question for the set of problems, and all of the associated
9598 * problems will be either fixed or not fixed.
9599 */
9600static struct latch_descr pr_latch_info[] = {
9601        { PR_LATCH_BLOCK, PR_1_INODE_BLOCK_LATCH, 0 },
9602        { PR_LATCH_BBLOCK, PR_1_INODE_BBLOCK_LATCH, 0 },
9603        { PR_LATCH_IBITMAP, PR_5_INODE_BITMAP_HEADER, PR_5_INODE_BITMAP_END },
9604        { PR_LATCH_BBITMAP, PR_5_BLOCK_BITMAP_HEADER, PR_5_BLOCK_BITMAP_END },
9605        { PR_LATCH_RELOC, PR_0_RELOCATE_HINT, 0 },
9606        { PR_LATCH_DBLOCK, PR_1B_DUP_BLOCK_HEADER, PR_1B_DUP_BLOCK_END },
9607        { PR_LATCH_LOW_DTIME, PR_1_ORPHAN_LIST_REFUGEES, 0 },
9608        { PR_LATCH_TOOBIG, PR_1_INODE_TOOBIG, 0 },
9609        { PR_LATCH_OPTIMIZE_DIR, PR_3A_OPTIMIZE_DIR_HEADER, PR_3A_OPTIMIZE_DIR_END },
9610        { -1, 0, 0 },
9611};
9612
9613static const struct e2fsck_problem *find_problem(problem_t code)
9614{
9615        int     i;
9616
9617        for (i=0; problem_table[i].e2p_code; i++) {
9618                if (problem_table[i].e2p_code == code)
9619                        return &problem_table[i];
9620        }
9621        return 0;
9622}
9623
9624static struct latch_descr *find_latch(int code)
9625{
9626        int     i;
9627
9628        for (i=0; pr_latch_info[i].latch_code >= 0; i++) {
9629                if (pr_latch_info[i].latch_code == code)
9630                        return &pr_latch_info[i];
9631        }
9632        return 0;
9633}
9634
9635int end_problem_latch(e2fsck_t ctx, int mask)
9636{
9637        struct latch_descr *ldesc;
9638        struct problem_context pctx;
9639        int answer = -1;
9640
9641        ldesc = find_latch(mask);
9642        if (ldesc->end_message && (ldesc->flags & PRL_LATCHED)) {
9643                clear_problem_context(&pctx);
9644                answer = fix_problem(ctx, ldesc->end_message, &pctx);
9645        }
9646        ldesc->flags &= ~(PRL_VARIABLE);
9647        return answer;
9648}
9649
9650int set_latch_flags(int mask, int setflags, int clearflags)
9651{
9652        struct latch_descr *ldesc;
9653
9654        ldesc = find_latch(mask);
9655        if (!ldesc)
9656                return -1;
9657        ldesc->flags |= setflags;
9658        ldesc->flags &= ~clearflags;
9659        return 0;
9660}
9661
9662void clear_problem_context(struct problem_context *ctx)
9663{
9664        memset(ctx, 0, sizeof(struct problem_context));
9665        ctx->blkcount = -1;
9666        ctx->group = -1;
9667}
9668
9669int fix_problem(e2fsck_t ctx, problem_t code, struct problem_context *pctx)
9670{
9671        ext2_filsys fs = ctx->fs;
9672        const struct e2fsck_problem *ptr;
9673        struct latch_descr *ldesc = 0;
9674        const char *message;
9675        int             def_yn, answer, ans;
9676        int             print_answer = 0;
9677        int             suppress = 0;
9678
9679        ptr = find_problem(code);
9680        if (!ptr) {
9681                printf(_("Unhandled error code (0x%x)!\n"), code);
9682                return 0;
9683        }
9684        def_yn = 1;
9685        if ((ptr->flags & PR_NO_DEFAULT) ||
9686            ((ptr->flags & PR_PREEN_NO) && (ctx->options & E2F_OPT_PREEN)) ||
9687            (ctx->options & E2F_OPT_NO))
9688                def_yn= 0;
9689
9690        /*
9691         * Do special latch processing.  This is where we ask the
9692         * latch question, if it exists
9693         */
9694        if (ptr->flags & PR_LATCH_MASK) {
9695                ldesc = find_latch(ptr->flags & PR_LATCH_MASK);
9696                if (ldesc->question && !(ldesc->flags & PRL_LATCHED)) {
9697                        ans = fix_problem(ctx, ldesc->question, pctx);
9698                        if (ans == 1)
9699                                ldesc->flags |= PRL_YES;
9700                        if (ans == 0)
9701                                ldesc->flags |= PRL_NO;
9702                        ldesc->flags |= PRL_LATCHED;
9703                }
9704                if (ldesc->flags & PRL_SUPPRESS)
9705                        suppress++;
9706        }
9707        if ((ptr->flags & PR_PREEN_NOMSG) &&
9708            (ctx->options & E2F_OPT_PREEN))
9709                suppress++;
9710        if ((ptr->flags & PR_NO_NOMSG) &&
9711            (ctx->options & E2F_OPT_NO))
9712                suppress++;
9713        if (!suppress) {
9714                message = ptr->e2p_description;
9715                if ((ctx->options & E2F_OPT_PREEN) &&
9716                    !(ptr->flags & PR_PREEN_NOHDR)) {
9717                        printf("%s: ", ctx->device_name ?
9718                               ctx->device_name : ctx->filesystem_name);
9719                }
9720                if (*message)
9721                        print_e2fsck_message(ctx, _(message), pctx, 1);
9722        }
9723        if (!(ptr->flags & PR_PREEN_OK) && (ptr->prompt != PROMPT_NONE))
9724                preenhalt(ctx);
9725
9726        if (ptr->flags & PR_FATAL)
9727                bb_error_msg_and_die(0);
9728
9729        if (ptr->prompt == PROMPT_NONE) {
9730                if (ptr->flags & PR_NOCOLLATE)
9731                        answer = -1;
9732                else
9733                        answer = def_yn;
9734        } else {
9735                if (ctx->options & E2F_OPT_PREEN) {
9736                        answer = def_yn;
9737                        if (!(ptr->flags & PR_PREEN_NOMSG))
9738                                print_answer = 1;
9739                } else if ((ptr->flags & PR_LATCH_MASK) &&
9740                           (ldesc->flags & (PRL_YES | PRL_NO))) {
9741                        if (!suppress)
9742                                print_answer = 1;
9743                        if (ldesc->flags & PRL_YES)
9744                                answer = 1;
9745                        else
9746                                answer = 0;
9747                } else
9748                        answer = ask(ctx, _(prompt[(int) ptr->prompt]), def_yn);
9749                if (!answer && !(ptr->flags & PR_NO_OK))
9750                        ext2fs_unmark_valid(fs);
9751
9752                if (print_answer)
9753                        printf("%s.\n", answer ?
9754                               _(preen_msg[(int) ptr->prompt]) : _("IGNORED"));
9755
9756        }
9757
9758        if ((ptr->prompt == PROMPT_ABORT) && answer)
9759                bb_error_msg_and_die(0);
9760
9761        if (ptr->flags & PR_AFTER_CODE)
9762                answer = fix_problem(ctx, ptr->second_code, pctx);
9763
9764        return answer;
9765}
9766
9767/*
9768 * linux/fs/recovery.c
9769 *
9770 * Written by Stephen C. Tweedie <sct@redhat.com>, 1999
9771 */
9772
9773/*
9774 * Maintain information about the progress of the recovery job, so that
9775 * the different passes can carry information between them.
9776 */
9777struct recovery_info
9778{
9779        tid_t           start_transaction;
9780        tid_t           end_transaction;
9781
9782        int             nr_replays;
9783        int             nr_revokes;
9784        int             nr_revoke_hits;
9785};
9786
9787enum passtype {PASS_SCAN, PASS_REVOKE, PASS_REPLAY};
9788static int do_one_pass(journal_t *journal,
9789                                struct recovery_info *info, enum passtype pass);
9790static int scan_revoke_records(journal_t *, struct buffer_head *,
9791                                tid_t, struct recovery_info *);
9792
9793/*
9794 * Read a block from the journal
9795 */
9796
9797static int jread(struct buffer_head **bhp, journal_t *journal,
9798                 unsigned int offset)
9799{
9800        int err;
9801        unsigned long blocknr;
9802        struct buffer_head *bh;
9803
9804        *bhp = NULL;
9805
9806        err = journal_bmap(journal, offset, &blocknr);
9807
9808        if (err) {
9809                printf("JBD: bad block at offset %u\n", offset);
9810                return err;
9811        }
9812
9813        bh = getblk(journal->j_dev, blocknr, journal->j_blocksize);
9814        if (!bh)
9815                return -ENOMEM;
9816
9817        if (!buffer_uptodate(bh)) {
9818                /* If this is a brand new buffer, start readahead.
9819                   Otherwise, we assume we are already reading it.  */
9820                if (!buffer_req(bh))
9821                        do_readahead(journal, offset);
9822                wait_on_buffer(bh);
9823        }
9824
9825        if (!buffer_uptodate(bh)) {
9826                printf("JBD: Failed to read block at offset %u\n", offset);
9827                brelse(bh);
9828                return -EIO;
9829        }
9830
9831        *bhp = bh;
9832        return 0;
9833}
9834
9835
9836/*
9837 * Count the number of in-use tags in a journal descriptor block.
9838 */
9839
9840static int count_tags(struct buffer_head *bh, int size)
9841{
9842        char *                  tagp;
9843        journal_block_tag_t *   tag;
9844        int                     nr = 0;
9845
9846        tagp = &bh->b_data[sizeof(journal_header_t)];
9847
9848        while ((tagp - bh->b_data + sizeof(journal_block_tag_t)) <= size) {
9849                tag = (journal_block_tag_t *) tagp;
9850
9851                nr++;
9852                tagp += sizeof(journal_block_tag_t);
9853                if (!(tag->t_flags & htonl(JFS_FLAG_SAME_UUID)))
9854                        tagp += 16;
9855
9856                if (tag->t_flags & htonl(JFS_FLAG_LAST_TAG))
9857                        break;
9858        }
9859
9860        return nr;
9861}
9862
9863
9864/* Make sure we wrap around the log correctly! */
9865#define wrap(journal, var)                                            \
9866do {                                                                \
9867        if (var >= (journal)->j_last)                                   \
9868                var -= ((journal)->j_last - (journal)->j_first);        \
9869} while (0)
9870
9871/**
9872 * int journal_recover(journal_t *journal) - recovers a on-disk journal
9873 * @journal: the journal to recover
9874 *
9875 * The primary function for recovering the log contents when mounting a
9876 * journaled device.
9877 *
9878 * Recovery is done in three passes.  In the first pass, we look for the
9879 * end of the log.  In the second, we assemble the list of revoke
9880 * blocks.  In the third and final pass, we replay any un-revoked blocks
9881 * in the log.
9882 */
9883int journal_recover(journal_t *journal)
9884{
9885        int                     err;
9886        journal_superblock_t *  sb;
9887
9888        struct recovery_info    info;
9889
9890        memset(&info, 0, sizeof(info));
9891        sb = journal->j_superblock;
9892
9893        /*
9894         * The journal superblock's s_start field (the current log head)
9895         * is always zero if, and only if, the journal was cleanly
9896         * unmounted.
9897         */
9898
9899        if (!sb->s_start) {
9900                journal->j_transaction_sequence = ntohl(sb->s_sequence) + 1;
9901                return 0;
9902        }
9903
9904        err = do_one_pass(journal, &info, PASS_SCAN);
9905        if (!err)
9906                err = do_one_pass(journal, &info, PASS_REVOKE);
9907        if (!err)
9908                err = do_one_pass(journal, &info, PASS_REPLAY);
9909
9910        /* Restart the log at the next transaction ID, thus invalidating
9911         * any existing commit records in the log. */
9912        journal->j_transaction_sequence = ++info.end_transaction;
9913
9914        journal_clear_revoke(journal);
9915        sync_blockdev(journal->j_fs_dev);
9916        return err;
9917}
9918
9919static int do_one_pass(journal_t *journal,
9920                        struct recovery_info *info, enum passtype pass)
9921{
9922        unsigned int            first_commit_ID, next_commit_ID;
9923        unsigned long           next_log_block;
9924        int                     err, success = 0;
9925        journal_superblock_t *  sb;
9926        journal_header_t *      tmp;
9927        struct buffer_head *    bh;
9928        unsigned int            sequence;
9929        int                     blocktype;
9930
9931        /* Precompute the maximum metadata descriptors in a descriptor block */
9932        int                     MAX_BLOCKS_PER_DESC;
9933        MAX_BLOCKS_PER_DESC = ((journal->j_blocksize-sizeof(journal_header_t))
9934                               / sizeof(journal_block_tag_t));
9935
9936        /*
9937         * First thing is to establish what we expect to find in the log
9938         * (in terms of transaction IDs), and where (in terms of log
9939         * block offsets): query the superblock.
9940         */
9941
9942        sb = journal->j_superblock;
9943        next_commit_ID = ntohl(sb->s_sequence);
9944        next_log_block = ntohl(sb->s_start);
9945
9946        first_commit_ID = next_commit_ID;
9947        if (pass == PASS_SCAN)
9948                info->start_transaction = first_commit_ID;
9949
9950        /*
9951         * Now we walk through the log, transaction by transaction,
9952         * making sure that each transaction has a commit block in the
9953         * expected place.  Each complete transaction gets replayed back
9954         * into the main filesystem.
9955         */
9956
9957        while (1) {
9958                int                     flags;
9959                char *                  tagp;
9960                journal_block_tag_t *   tag;
9961                struct buffer_head *    obh;
9962                struct buffer_head *    nbh;
9963
9964                /* If we already know where to stop the log traversal,
9965                 * check right now that we haven't gone past the end of
9966                 * the log. */
9967
9968                if (pass != PASS_SCAN)
9969                        if (tid_geq(next_commit_ID, info->end_transaction))
9970                                break;
9971
9972                /* Skip over each chunk of the transaction looking
9973                 * either the next descriptor block or the final commit
9974                 * record. */
9975
9976                err = jread(&bh, journal, next_log_block);
9977                if (err)
9978                        goto failed;
9979
9980                next_log_block++;
9981                wrap(journal, next_log_block);
9982
9983                /* What kind of buffer is it?
9984                 *
9985                 * If it is a descriptor block, check that it has the
9986                 * expected sequence number.  Otherwise, we're all done
9987                 * here. */
9988
9989                tmp = (journal_header_t *)bh->b_data;
9990
9991                if (tmp->h_magic != htonl(JFS_MAGIC_NUMBER)) {
9992                        brelse(bh);
9993                        break;
9994                }
9995
9996                blocktype = ntohl(tmp->h_blocktype);
9997                sequence = ntohl(tmp->h_sequence);
9998
9999                if (sequence != next_commit_ID) {
10000                        brelse(bh);
10001                        break;
10002                }
10003
10004                /* OK, we have a valid descriptor block which matches
10005                 * all of the sequence number checks.  What are we going
10006                 * to do with it?  That depends on the pass... */
10007
10008                switch (blocktype) {
10009                case JFS_DESCRIPTOR_BLOCK:
10010                        /* If it is a valid descriptor block, replay it
10011                         * in pass REPLAY; otherwise, just skip over the
10012                         * blocks it describes. */
10013                        if (pass != PASS_REPLAY) {
10014                                next_log_block +=
10015                                        count_tags(bh, journal->j_blocksize);
10016                                wrap(journal, next_log_block);
10017                                brelse(bh);
10018                                continue;
10019                        }
10020
10021                        /* A descriptor block: we can now write all of
10022                         * the data blocks.  Yay, useful work is finally
10023                         * getting done here! */
10024
10025                        tagp = &bh->b_data[sizeof(journal_header_t)];
10026                        while ((tagp - bh->b_data +sizeof(journal_block_tag_t))
10027                               <= journal->j_blocksize) {
10028                                unsigned long io_block;
10029
10030                                tag = (journal_block_tag_t *) tagp;
10031                                flags = ntohl(tag->t_flags);
10032
10033                                io_block = next_log_block++;
10034                                wrap(journal, next_log_block);
10035                                err = jread(&obh, journal, io_block);
10036                                if (err) {
10037                                        /* Recover what we can, but
10038                                         * report failure at the end. */
10039                                        success = err;
10040                                        printf("JBD: IO error %d recovering "
10041                                                "block %ld in log\n",
10042                                                err, io_block);
10043                                } else {
10044                                        unsigned long blocknr;
10045
10046                                        blocknr = ntohl(tag->t_blocknr);
10047
10048                                        /* If the block has been
10049                                         * revoked, then we're all done
10050                                         * here. */
10051                                        if (journal_test_revoke
10052                                            (journal, blocknr,
10053                                             next_commit_ID)) {
10054                                                brelse(obh);
10055                                                ++info->nr_revoke_hits;
10056                                                goto skip_write;
10057                                        }
10058
10059                                        /* Find a buffer for the new
10060                                         * data being restored */
10061                                        nbh = getblk(journal->j_fs_dev,
10062                                                       blocknr,
10063                                                     journal->j_blocksize);
10064                                        if (nbh == NULL) {
10065                                                printf("JBD: Out of memory "
10066                                                       "during recovery.\n");
10067                                                err = -ENOMEM;
10068                                                brelse(bh);
10069                                                brelse(obh);
10070                                                goto failed;
10071                                        }
10072
10073                                        lock_buffer(nbh);
10074                                        memcpy(nbh->b_data, obh->b_data,
10075                                                        journal->j_blocksize);
10076                                        if (flags & JFS_FLAG_ESCAPE) {
10077                                                *((unsigned int *)bh->b_data) =
10078                                                        htonl(JFS_MAGIC_NUMBER);
10079                                        }
10080
10081                                        mark_buffer_uptodate(nbh, 1);
10082                                        mark_buffer_dirty(nbh);
10083                                        ++info->nr_replays;
10084                                        /* ll_rw_block(WRITE, 1, &nbh); */
10085                                        unlock_buffer(nbh);
10086                                        brelse(obh);
10087                                        brelse(nbh);
10088                                }
10089
10090                        skip_write:
10091                                tagp += sizeof(journal_block_tag_t);
10092                                if (!(flags & JFS_FLAG_SAME_UUID))
10093                                        tagp += 16;
10094
10095                                if (flags & JFS_FLAG_LAST_TAG)
10096                                        break;
10097                        }
10098
10099                        brelse(bh);
10100                        continue;
10101
10102                case JFS_COMMIT_BLOCK:
10103                        /* Found an expected commit block: not much to
10104                         * do other than move on to the next sequence
10105                         * number. */
10106                        brelse(bh);
10107                        next_commit_ID++;
10108                        continue;
10109
10110                case JFS_REVOKE_BLOCK:
10111                        /* If we aren't in the REVOKE pass, then we can
10112                         * just skip over this block. */
10113                        if (pass != PASS_REVOKE) {
10114                                brelse(bh);
10115                                continue;
10116                        }
10117
10118                        err = scan_revoke_records(journal, bh,
10119                                                  next_commit_ID, info);
10120                        brelse(bh);
10121                        if (err)
10122                                goto failed;
10123                        continue;
10124
10125                default:
10126                        goto done;
10127                }
10128        }
10129
10130 done:
10131        /*
10132         * We broke out of the log scan loop: either we came to the
10133         * known end of the log or we found an unexpected block in the
10134         * log.  If the latter happened, then we know that the "current"
10135         * transaction marks the end of the valid log.
10136         */
10137
10138        if (pass == PASS_SCAN)
10139                info->end_transaction = next_commit_ID;
10140        else {
10141                /* It's really bad news if different passes end up at
10142                 * different places (but possible due to IO errors). */
10143                if (info->end_transaction != next_commit_ID) {
10144                        printf("JBD: recovery pass %d ended at "
10145                                "transaction %u, expected %u\n",
10146                                pass, next_commit_ID, info->end_transaction);
10147                        if (!success)
10148                                success = -EIO;
10149                }
10150        }
10151
10152        return success;
10153
10154 failed:
10155        return err;
10156}
10157
10158
10159/* Scan a revoke record, marking all blocks mentioned as revoked. */
10160
10161static int scan_revoke_records(journal_t *journal, struct buffer_head *bh,
10162                               tid_t sequence, struct recovery_info *info)
10163{
10164        journal_revoke_header_t *header;
10165        int offset, max;
10166
10167        header = (journal_revoke_header_t *) bh->b_data;
10168        offset = sizeof(journal_revoke_header_t);
10169        max = ntohl(header->r_count);
10170
10171        while (offset < max) {
10172                unsigned long blocknr;
10173                int err;
10174
10175                blocknr = ntohl(* ((unsigned int *) (bh->b_data+offset)));
10176                offset += 4;
10177                err = journal_set_revoke(journal, blocknr, sequence);
10178                if (err)
10179                        return err;
10180                ++info->nr_revokes;
10181        }
10182        return 0;
10183}
10184
10185
10186/*
10187 * rehash.c --- rebuild hash tree directories
10188 *
10189 * This algorithm is designed for simplicity of implementation and to
10190 * pack the directory as much as possible.  It however requires twice
10191 * as much memory as the size of the directory.  The maximum size
10192 * directory supported using a 4k blocksize is roughly a gigabyte, and
10193 * so there may very well be problems with machines that don't have
10194 * virtual memory, and obscenely large directories.
10195 *
10196 * An alternate algorithm which is much more disk intensive could be
10197 * written, and probably will need to be written in the future.  The
10198 * design goals of such an algorithm are: (a) use (roughly) constant
10199 * amounts of memory, no matter how large the directory, (b) the
10200 * directory must be safe at all times, even if e2fsck is interrupted
10201 * in the middle, (c) we must use minimal amounts of extra disk
10202 * blocks.  This pretty much requires an incremental approach, where
10203 * we are reading from one part of the directory, and inserting into
10204 * the front half.  So the algorithm will have to keep track of a
10205 * moving block boundary between the new tree and the old tree, and
10206 * files will need to be moved from the old directory and inserted
10207 * into the new tree.  If the new directory requires space which isn't
10208 * yet available, blocks from the beginning part of the old directory
10209 * may need to be moved to the end of the directory to make room for
10210 * the new tree:
10211 *
10212 *    --------------------------------------------------------
10213 *    |  new tree   |        | old tree                      |
10214 *    --------------------------------------------------------
10215 *                  ^ ptr    ^ptr
10216 *                tail new   head old
10217 *
10218 * This is going to be a pain in the tuckus to implement, and will
10219 * require a lot more disk accesses.  So I'm going to skip it for now;
10220 * it's only really going to be an issue for really, really big
10221 * filesystems (when we reach the level of tens of millions of files
10222 * in a single directory).  It will probably be easier to simply
10223 * require that e2fsck use VM first.
10224 */
10225
10226struct fill_dir_struct {
10227        char *buf;
10228        struct ext2_inode *inode;
10229        int err;
10230        e2fsck_t ctx;
10231        struct hash_entry *harray;
10232        int max_array, num_array;
10233        int dir_size;
10234        int compress;
10235        ino_t parent;
10236};
10237
10238struct hash_entry {
10239        ext2_dirhash_t  hash;
10240        ext2_dirhash_t  minor_hash;
10241        struct ext2_dir_entry   *dir;
10242};
10243
10244struct out_dir {
10245        int             num;
10246        int             max;
10247        char            *buf;
10248        ext2_dirhash_t  *hashes;
10249};
10250
10251static int fill_dir_block(ext2_filsys fs,
10252                          blk_t *block_nr,
10253                          e2_blkcnt_t blockcnt,
10254                          blk_t ref_block FSCK_ATTR((unused)),
10255                          int ref_offset FSCK_ATTR((unused)),
10256                          void *priv_data)
10257{
10258        struct fill_dir_struct  *fd = (struct fill_dir_struct *) priv_data;
10259        struct hash_entry       *new_array, *ent;
10260        struct ext2_dir_entry   *dirent;
10261        char                    *dir;
10262        unsigned int            offset, dir_offset;
10263
10264        if (blockcnt < 0)
10265                return 0;
10266
10267        offset = blockcnt * fs->blocksize;
10268        if (offset + fs->blocksize > fd->inode->i_size) {
10269                fd->err = EXT2_ET_DIR_CORRUPTED;
10270                return BLOCK_ABORT;
10271        }
10272        dir = (fd->buf+offset);
10273        if (HOLE_BLKADDR(*block_nr)) {
10274                memset(dir, 0, fs->blocksize);
10275                dirent = (struct ext2_dir_entry *) dir;
10276                dirent->rec_len = fs->blocksize;
10277        } else {
10278                fd->err = ext2fs_read_dir_block(fs, *block_nr, dir);
10279                if (fd->err)
10280                        return BLOCK_ABORT;
10281        }
10282        /* While the directory block is "hot", index it. */
10283        dir_offset = 0;
10284        while (dir_offset < fs->blocksize) {
10285                dirent = (struct ext2_dir_entry *) (dir + dir_offset);
10286                if (((dir_offset + dirent->rec_len) > fs->blocksize) ||
10287                    (dirent->rec_len < 8) ||
10288                    ((dirent->rec_len % 4) != 0) ||
10289                    (((dirent->name_len & 0xFF)+8) > dirent->rec_len)) {
10290                        fd->err = EXT2_ET_DIR_CORRUPTED;
10291                        return BLOCK_ABORT;
10292                }
10293                dir_offset += dirent->rec_len;
10294                if (dirent->inode == 0)
10295                        continue;
10296                if (!fd->compress && ((dirent->name_len&0xFF) == 1) &&
10297                    (dirent->name[0] == '.'))
10298                        continue;
10299                if (!fd->compress && ((dirent->name_len&0xFF) == 2) &&
10300                    (dirent->name[0] == '.') && (dirent->name[1] == '.')) {
10301                        fd->parent = dirent->inode;
10302                        continue;
10303                }
10304                if (fd->num_array >= fd->max_array) {
10305                        new_array = xrealloc(fd->harray,
10306                            sizeof(struct hash_entry) * (fd->max_array+500));
10307                        fd->harray = new_array;
10308                        fd->max_array += 500;
10309                }
10310                ent = fd->harray + fd->num_array++;
10311                ent->dir = dirent;
10312                fd->dir_size += EXT2_DIR_REC_LEN(dirent->name_len & 0xFF);
10313                if (fd->compress)
10314                        ent->hash = ent->minor_hash = 0;
10315                else {
10316                        fd->err = ext2fs_dirhash(fs->super->s_def_hash_version,
10317                                                 dirent->name,
10318                                                 dirent->name_len & 0xFF,
10319                                                 fs->super->s_hash_seed,
10320                                                 &ent->hash, &ent->minor_hash);
10321                        if (fd->err)
10322                                return BLOCK_ABORT;
10323                }
10324        }
10325
10326        return 0;
10327}
10328
10329/* Used for sorting the hash entry */
10330static int name_cmp(const void *a, const void *b)
10331{
10332        const struct hash_entry *he_a = (const struct hash_entry *) a;
10333        const struct hash_entry *he_b = (const struct hash_entry *) b;
10334        int     ret;
10335        int     min_len;
10336
10337        min_len = he_a->dir->name_len;
10338        if (min_len > he_b->dir->name_len)
10339                min_len = he_b->dir->name_len;
10340
10341        ret = strncmp(he_a->dir->name, he_b->dir->name, min_len);
10342        if (ret == 0) {
10343                if (he_a->dir->name_len > he_b->dir->name_len)
10344                        ret = 1;
10345                else if (he_a->dir->name_len < he_b->dir->name_len)
10346                        ret = -1;
10347                else
10348                        ret = he_b->dir->inode - he_a->dir->inode;
10349        }
10350        return ret;
10351}
10352
10353/* Used for sorting the hash entry */
10354static int hash_cmp(const void *a, const void *b)
10355{
10356        const struct hash_entry *he_a = (const struct hash_entry *) a;
10357        const struct hash_entry *he_b = (const struct hash_entry *) b;
10358        int     ret;
10359
10360        if (he_a->hash > he_b->hash)
10361                ret = 1;
10362        else if (he_a->hash < he_b->hash)
10363                ret = -1;
10364        else {
10365                if (he_a->minor_hash > he_b->minor_hash)
10366                        ret = 1;
10367                else if (he_a->minor_hash < he_b->minor_hash)
10368                        ret = -1;
10369                else
10370                        ret = name_cmp(a, b);
10371        }
10372        return ret;
10373}
10374
10375static errcode_t alloc_size_dir(ext2_filsys fs, struct out_dir *outdir,
10376                                int blocks)
10377{
10378        void                    *new_mem;
10379
10380        if (outdir->max) {
10381                new_mem = xrealloc(outdir->buf, blocks * fs->blocksize);
10382                outdir->buf = new_mem;
10383                new_mem = xrealloc(outdir->hashes,
10384                                  blocks * sizeof(ext2_dirhash_t));
10385                outdir->hashes = new_mem;
10386        } else {
10387                outdir->buf = xmalloc(blocks * fs->blocksize);
10388                outdir->hashes = xmalloc(blocks * sizeof(ext2_dirhash_t));
10389                outdir->num = 0;
10390        }
10391        outdir->max = blocks;
10392        return 0;
10393}
10394
10395static void free_out_dir(struct out_dir *outdir)
10396{
10397        free(outdir->buf);
10398        free(outdir->hashes);
10399        outdir->max = 0;
10400        outdir->num =0;
10401}
10402
10403static errcode_t get_next_block(ext2_filsys fs, struct out_dir *outdir,
10404                         char ** ret)
10405{
10406        errcode_t       retval;
10407
10408        if (outdir->num >= outdir->max) {
10409                retval = alloc_size_dir(fs, outdir, outdir->max + 50);
10410                if (retval)
10411                        return retval;
10412        }
10413        *ret = outdir->buf + (outdir->num++ * fs->blocksize);
10414        memset(*ret, 0, fs->blocksize);
10415        return 0;
10416}
10417
10418/*
10419 * This function is used to make a unique filename.  We do this by
10420 * appending ~0, and then incrementing the number.  However, we cannot
10421 * expand the length of the filename beyond the padding available in
10422 * the directory entry.
10423 */
10424static void mutate_name(char *str, __u16 *len)
10425{
10426        int     i;
10427        __u16   l = *len & 0xFF, h = *len & 0xff00;
10428
10429        /*
10430         * First check to see if it looks the name has been mutated
10431         * already
10432         */
10433        for (i = l-1; i > 0; i--) {
10434                if (!isdigit(str[i]))
10435                        break;
10436        }
10437        if ((i == l-1) || (str[i] != '~')) {
10438                if (((l-1) & 3) < 2)
10439                        l += 2;
10440                else
10441                        l = (l+3) & ~3;
10442                str[l-2] = '~';
10443                str[l-1] = '0';
10444                *len = l | h;
10445                return;
10446        }
10447        for (i = l-1; i >= 0; i--) {
10448                if (isdigit(str[i])) {
10449                        if (str[i] == '9')
10450                                str[i] = '0';
10451                        else {
10452                                str[i]++;
10453                                return;
10454                        }
10455                        continue;
10456                }
10457                if (i == 1) {
10458                        if (str[0] == 'z')
10459                                str[0] = 'A';
10460                        else if (str[0] == 'Z') {
10461                                str[0] = '~';
10462                                str[1] = '0';
10463                        } else
10464                                str[0]++;
10465                } else if (i > 0) {
10466                        str[i] = '1';
10467                        str[i-1] = '~';
10468                } else {
10469                        if (str[0] == '~')
10470                                str[0] = 'a';
10471                        else
10472                                str[0]++;
10473                }
10474                break;
10475        }
10476}
10477
10478static int duplicate_search_and_fix(e2fsck_t ctx, ext2_filsys fs,
10479                                    ext2_ino_t ino,
10480                                    struct fill_dir_struct *fd)
10481{
10482        struct problem_context  pctx;
10483        struct hash_entry       *ent, *prev;
10484        int                     i, j;
10485        int                     fixed = 0;
10486        char                    new_name[256];
10487        __u16                   new_len;
10488
10489        clear_problem_context(&pctx);
10490        pctx.ino = ino;
10491
10492        for (i=1; i < fd->num_array; i++) {
10493                ent = fd->harray + i;
10494                prev = ent - 1;
10495                if (!ent->dir->inode ||
10496                    ((ent->dir->name_len & 0xFF) !=
10497                     (prev->dir->name_len & 0xFF)) ||
10498                    (strncmp(ent->dir->name, prev->dir->name,
10499                             ent->dir->name_len & 0xFF)))
10500                        continue;
10501                pctx.dirent = ent->dir;
10502                if ((ent->dir->inode == prev->dir->inode) &&
10503                    fix_problem(ctx, PR_2_DUPLICATE_DIRENT, &pctx)) {
10504                        e2fsck_adjust_inode_count(ctx, ent->dir->inode, -1);
10505                        ent->dir->inode = 0;
10506                        fixed++;
10507                        continue;
10508                }
10509                memcpy(new_name, ent->dir->name, ent->dir->name_len & 0xFF);
10510                new_len = ent->dir->name_len;
10511                mutate_name(new_name, &new_len);
10512                for (j=0; j < fd->num_array; j++) {
10513                        if ((i==j) ||
10514                            ((ent->dir->name_len & 0xFF) !=
10515                             (fd->harray[j].dir->name_len & 0xFF)) ||
10516                            (strncmp(new_name, fd->harray[j].dir->name,
10517                                     new_len & 0xFF)))
10518                                continue;
10519                        mutate_name(new_name, &new_len);
10520
10521                        j = -1;
10522                }
10523                new_name[new_len & 0xFF] = 0;
10524                pctx.str = new_name;
10525                if (fix_problem(ctx, PR_2_NON_UNIQUE_FILE, &pctx)) {
10526                        memcpy(ent->dir->name, new_name, new_len & 0xFF);
10527                        ent->dir->name_len = new_len;
10528                        ext2fs_dirhash(fs->super->s_def_hash_version,
10529                                       ent->dir->name,
10530                                       ent->dir->name_len & 0xFF,
10531                                       fs->super->s_hash_seed,
10532                                       &ent->hash, &ent->minor_hash);
10533                        fixed++;
10534                }
10535        }
10536        return fixed;
10537}
10538
10539
10540static errcode_t copy_dir_entries(ext2_filsys fs,
10541                                  struct fill_dir_struct *fd,
10542                                  struct out_dir *outdir)
10543{
10544        errcode_t               retval;
10545        char                    *block_start;
10546        struct hash_entry       *ent;
10547        struct ext2_dir_entry   *dirent;
10548        int                     i, rec_len, left;
10549        ext2_dirhash_t          prev_hash;
10550        int                     offset;
10551
10552        outdir->max = 0;
10553        retval = alloc_size_dir(fs, outdir,
10554                                (fd->dir_size / fs->blocksize) + 2);
10555        if (retval)
10556                return retval;
10557        outdir->num = fd->compress ? 0 : 1;
10558        offset = 0;
10559        outdir->hashes[0] = 0;
10560        prev_hash = 1;
10561        if ((retval = get_next_block(fs, outdir, &block_start)))
10562                return retval;
10563        dirent = (struct ext2_dir_entry *) block_start;
10564        left = fs->blocksize;
10565        for (i=0; i < fd->num_array; i++) {
10566                ent = fd->harray + i;
10567                if (ent->dir->inode == 0)
10568                        continue;
10569                rec_len = EXT2_DIR_REC_LEN(ent->dir->name_len & 0xFF);
10570                if (rec_len > left) {
10571                        if (left)
10572                                dirent->rec_len += left;
10573                        if ((retval = get_next_block(fs, outdir,
10574                                                      &block_start)))
10575                                return retval;
10576                        offset = 0;
10577                }
10578                left = fs->blocksize - offset;
10579                dirent = (struct ext2_dir_entry *) (block_start + offset);
10580                if (offset == 0) {
10581                        if (ent->hash == prev_hash)
10582                                outdir->hashes[outdir->num-1] = ent->hash | 1;
10583                        else
10584                                outdir->hashes[outdir->num-1] = ent->hash;
10585                }
10586                dirent->inode = ent->dir->inode;
10587                dirent->name_len = ent->dir->name_len;
10588                dirent->rec_len = rec_len;
10589                memcpy(dirent->name, ent->dir->name, dirent->name_len & 0xFF);
10590                offset += rec_len;
10591                left -= rec_len;
10592                if (left < 12) {
10593                        dirent->rec_len += left;
10594                        offset += left;
10595                        left = 0;
10596                }
10597                prev_hash = ent->hash;
10598        }
10599        if (left)
10600                dirent->rec_len += left;
10601
10602        return 0;
10603}
10604
10605
10606static struct ext2_dx_root_info *set_root_node(ext2_filsys fs, char *buf,
10607                                    ext2_ino_t ino, ext2_ino_t parent)
10608{
10609        struct ext2_dir_entry           *dir;
10610        struct ext2_dx_root_info        *root;
10611        struct ext2_dx_countlimit       *limits;
10612        int                             filetype = 0;
10613
10614        if (fs->super->s_feature_incompat & EXT2_FEATURE_INCOMPAT_FILETYPE)
10615                filetype = EXT2_FT_DIR << 8;
10616
10617        memset(buf, 0, fs->blocksize);
10618        dir = (struct ext2_dir_entry *) buf;
10619        dir->inode = ino;
10620        dir->name[0] = '.';
10621        dir->name_len = 1 | filetype;
10622        dir->rec_len = 12;
10623        dir = (struct ext2_dir_entry *) (buf + 12);
10624        dir->inode = parent;
10625        dir->name[0] = '.';
10626        dir->name[1] = '.';
10627        dir->name_len = 2 | filetype;
10628        dir->rec_len = fs->blocksize - 12;
10629
10630        root = (struct ext2_dx_root_info *) (buf+24);
10631        root->reserved_zero = 0;
10632        root->hash_version = fs->super->s_def_hash_version;
10633        root->info_length = 8;
10634        root->indirect_levels = 0;
10635        root->unused_flags = 0;
10636
10637        limits = (struct ext2_dx_countlimit *) (buf+32);
10638        limits->limit = (fs->blocksize - 32) / sizeof(struct ext2_dx_entry);
10639        limits->count = 0;
10640
10641        return root;
10642}
10643
10644
10645static struct ext2_dx_entry *set_int_node(ext2_filsys fs, char *buf)
10646{
10647        struct ext2_dir_entry           *dir;
10648        struct ext2_dx_countlimit       *limits;
10649
10650        memset(buf, 0, fs->blocksize);
10651        dir = (struct ext2_dir_entry *) buf;
10652        dir->inode = 0;
10653        dir->rec_len = fs->blocksize;
10654
10655        limits = (struct ext2_dx_countlimit *) (buf+8);
10656        limits->limit = (fs->blocksize - 8) / sizeof(struct ext2_dx_entry);
10657        limits->count = 0;
10658
10659        return (struct ext2_dx_entry *) limits;
10660}
10661
10662/*
10663 * This function takes the leaf nodes which have been written in
10664 * outdir, and populates the root node and any necessary interior nodes.
10665 */
10666static errcode_t calculate_tree(ext2_filsys fs,
10667                                struct out_dir *outdir,
10668                                ext2_ino_t ino,
10669                                ext2_ino_t parent)
10670{
10671        struct ext2_dx_root_info        *root_info;
10672        struct ext2_dx_entry            *root, *dx_ent = 0;
10673        struct ext2_dx_countlimit       *root_limit, *limit;
10674        errcode_t                       retval;
10675        char                            * block_start;
10676        int                             i, c1, c2, nblks;
10677        int                             limit_offset, root_offset;
10678
10679        root_info = set_root_node(fs, outdir->buf, ino, parent);
10680        root_offset = limit_offset = ((char *) root_info - outdir->buf) +
10681                root_info->info_length;
10682        root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10683        c1 = root_limit->limit;
10684        nblks = outdir->num;
10685
10686        /* Write out the pointer blocks */
10687        if (nblks-1 <= c1) {
10688                /* Just write out the root block, and we're done */
10689                root = (struct ext2_dx_entry *) (outdir->buf + root_offset);
10690                for (i=1; i < nblks; i++) {
10691                        root->block = ext2fs_cpu_to_le32(i);
10692                        if (i != 1)
10693                                root->hash =
10694                                        ext2fs_cpu_to_le32(outdir->hashes[i]);
10695                        root++;
10696                        c1--;
10697                }
10698        } else {
10699                c2 = 0;
10700                limit = 0;
10701                root_info->indirect_levels = 1;
10702                for (i=1; i < nblks; i++) {
10703                        if (c1 == 0)
10704                                return ENOSPC;
10705                        if (c2 == 0) {
10706                                if (limit)
10707                                        limit->limit = limit->count =
10708                ext2fs_cpu_to_le16(limit->limit);
10709                                root = (struct ext2_dx_entry *)
10710                                        (outdir->buf + root_offset);
10711                                root->block = ext2fs_cpu_to_le32(outdir->num);
10712                                if (i != 1)
10713                                        root->hash =
10714                        ext2fs_cpu_to_le32(outdir->hashes[i]);
10715                                if ((retval =  get_next_block(fs, outdir,
10716                                                              &block_start)))
10717                                        return retval;
10718                                dx_ent = set_int_node(fs, block_start);
10719                                limit = (struct ext2_dx_countlimit *) dx_ent;
10720                                c2 = limit->limit;
10721                                root_offset += sizeof(struct ext2_dx_entry);
10722                                c1--;
10723                        }
10724                        dx_ent->block = ext2fs_cpu_to_le32(i);
10725                        if (c2 != limit->limit)
10726                                dx_ent->hash =
10727                                        ext2fs_cpu_to_le32(outdir->hashes[i]);
10728                        dx_ent++;
10729                        c2--;
10730                }
10731                limit->count = ext2fs_cpu_to_le16(limit->limit - c2);
10732                limit->limit = ext2fs_cpu_to_le16(limit->limit);
10733        }
10734        root_limit = (struct ext2_dx_countlimit *) (outdir->buf + limit_offset);
10735        root_limit->count = ext2fs_cpu_to_le16(root_limit->limit - c1);
10736        root_limit->limit = ext2fs_cpu_to_le16(root_limit->limit);
10737
10738        return 0;
10739}
10740
10741struct write_dir_struct {
10742        struct out_dir *outdir;
10743        errcode_t       err;
10744        e2fsck_t        ctx;
10745        int             cleared;
10746};
10747
10748/*
10749 * Helper function which writes out a directory block.
10750 */
10751static int write_dir_block(ext2_filsys fs,
10752                           blk_t        *block_nr,
10753                           e2_blkcnt_t blockcnt,
10754                           blk_t ref_block FSCK_ATTR((unused)),
10755                           int ref_offset FSCK_ATTR((unused)),
10756                           void *priv_data)
10757{
10758        struct write_dir_struct *wd = (struct write_dir_struct *) priv_data;
10759        blk_t   blk;
10760        char    *dir;
10761
10762        if (*block_nr == 0)
10763                return 0;
10764        if (blockcnt >= wd->outdir->num) {
10765                e2fsck_read_bitmaps(wd->ctx);
10766                blk = *block_nr;
10767                ext2fs_unmark_block_bitmap(wd->ctx->block_found_map, blk);
10768                ext2fs_block_alloc_stats(fs, blk, -1);
10769                *block_nr = 0;
10770                wd->cleared++;
10771                return BLOCK_CHANGED;
10772        }
10773        if (blockcnt < 0)
10774                return 0;
10775
10776        dir = wd->outdir->buf + (blockcnt * fs->blocksize);
10777        wd->err = ext2fs_write_dir_block(fs, *block_nr, dir);
10778        if (wd->err)
10779                return BLOCK_ABORT;
10780        return 0;
10781}
10782
10783static errcode_t write_directory(e2fsck_t ctx, ext2_filsys fs,
10784                                 struct out_dir *outdir,
10785                                 ext2_ino_t ino, int compress)
10786{
10787        struct write_dir_struct wd;
10788        errcode_t       retval;
10789        struct ext2_inode       inode;
10790
10791        retval = e2fsck_expand_directory(ctx, ino, -1, outdir->num);
10792        if (retval)
10793                return retval;
10794
10795        wd.outdir = outdir;
10796        wd.err = 0;
10797        wd.ctx = ctx;
10798        wd.cleared = 0;
10799
10800        retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10801                                       write_dir_block, &wd);
10802        if (retval)
10803                return retval;
10804        if (wd.err)
10805                return wd.err;
10806
10807        e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10808        if (compress)
10809                inode.i_flags &= ~EXT2_INDEX_FL;
10810        else
10811                inode.i_flags |= EXT2_INDEX_FL;
10812        inode.i_size = outdir->num * fs->blocksize;
10813        inode.i_blocks -= (fs->blocksize / 512) * wd.cleared;
10814        e2fsck_write_inode(ctx, ino, &inode, "rehash_dir");
10815
10816        return 0;
10817}
10818
10819static errcode_t e2fsck_rehash_dir(e2fsck_t ctx, ext2_ino_t ino)
10820{
10821        ext2_filsys             fs = ctx->fs;
10822        errcode_t               retval;
10823        struct ext2_inode       inode;
10824        char                    *dir_buf = 0;
10825        struct fill_dir_struct  fd;
10826        struct out_dir          outdir;
10827
10828        outdir.max = outdir.num = 0;
10829        outdir.buf = 0;
10830        outdir.hashes = 0;
10831        e2fsck_read_inode(ctx, ino, &inode, "rehash_dir");
10832
10833        retval = ENOMEM;
10834        fd.harray = 0;
10835        dir_buf = xmalloc(inode.i_size);
10836
10837        fd.max_array = inode.i_size / 32;
10838        fd.num_array = 0;
10839        fd.harray = xmalloc(fd.max_array * sizeof(struct hash_entry));
10840
10841        fd.ctx = ctx;
10842        fd.buf = dir_buf;
10843        fd.inode = &inode;
10844        fd.err = 0;
10845        fd.dir_size = 0;
10846        fd.compress = 0;
10847        if (!(fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) ||
10848            (inode.i_size / fs->blocksize) < 2)
10849                fd.compress = 1;
10850        fd.parent = 0;
10851
10852        /* Read in the entire directory into memory */
10853        retval = ext2fs_block_iterate2(fs, ino, 0, 0,
10854                                       fill_dir_block, &fd);
10855        if (fd.err) {
10856                retval = fd.err;
10857                goto errout;
10858        }
10859
10860        /* Sort the list */
10861resort:
10862        if (fd.compress)
10863                qsort(fd.harray+2, fd.num_array-2,
10864                      sizeof(struct hash_entry), name_cmp);
10865        else
10866                qsort(fd.harray, fd.num_array,
10867                      sizeof(struct hash_entry), hash_cmp);
10868
10869        /*
10870         * Look for duplicates
10871         */
10872        if (duplicate_search_and_fix(ctx, fs, ino, &fd))
10873                goto resort;
10874
10875        if (ctx->options & E2F_OPT_NO) {
10876                retval = 0;
10877                goto errout;
10878        }
10879
10880        /*
10881         * Copy the directory entries.  In a htree directory these
10882         * will become the leaf nodes.
10883         */
10884        retval = copy_dir_entries(fs, &fd, &outdir);
10885        if (retval)
10886                goto errout;
10887
10888        free(dir_buf); dir_buf = 0;
10889
10890        if (!fd.compress) {
10891                /* Calculate the interior nodes */
10892                retval = calculate_tree(fs, &outdir, ino, fd.parent);
10893                if (retval)
10894                        goto errout;
10895        }
10896
10897        retval = write_directory(ctx, fs, &outdir, ino, fd.compress);
10898
10899errout:
10900        free(dir_buf);
10901        free(fd.harray);
10902
10903        free_out_dir(&outdir);
10904        return retval;
10905}
10906
10907void e2fsck_rehash_directories(e2fsck_t ctx)
10908{
10909        struct problem_context  pctx;
10910        struct dir_info         *dir;
10911        ext2_u32_iterate        iter;
10912        ext2_ino_t              ino;
10913        errcode_t               retval;
10914        int                     i, cur, max, all_dirs, dir_index, first = 1;
10915
10916        all_dirs = ctx->options & E2F_OPT_COMPRESS_DIRS;
10917
10918        if (!ctx->dirs_to_hash && !all_dirs)
10919                return;
10920
10921        e2fsck_get_lost_and_found(ctx, 0);
10922
10923        clear_problem_context(&pctx);
10924
10925        dir_index = ctx->fs->super->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX;
10926        cur = 0;
10927        if (all_dirs) {
10928                i = 0;
10929                max = e2fsck_get_num_dirinfo(ctx);
10930        } else {
10931                retval = ext2fs_u32_list_iterate_begin(ctx->dirs_to_hash,
10932                                                       &iter);
10933                if (retval) {
10934                        pctx.errcode = retval;
10935                        fix_problem(ctx, PR_3A_OPTIMIZE_ITER, &pctx);
10936                        return;
10937                }
10938                max = ext2fs_u32_list_count(ctx->dirs_to_hash);
10939        }
10940        while (1) {
10941                if (all_dirs) {
10942                        if ((dir = e2fsck_dir_info_iter(ctx, &i)) == 0)
10943                                break;
10944                        ino = dir->ino;
10945                } else {
10946                        if (!ext2fs_u32_list_iterate(iter, &ino))
10947                                break;
10948                }
10949                if (ino == ctx->lost_and_found)
10950                        continue;
10951                pctx.dir = ino;
10952                if (first) {
10953                        fix_problem(ctx, PR_3A_PASS_HEADER, &pctx);
10954                        first = 0;
10955                }
10956                pctx.errcode = e2fsck_rehash_dir(ctx, ino);
10957                if (pctx.errcode) {
10958                        end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10959                        fix_problem(ctx, PR_3A_OPTIMIZE_DIR_ERR, &pctx);
10960                }
10961                if (ctx->progress && !ctx->progress_fd)
10962                        e2fsck_simple_progress(ctx, "Rebuilding directory",
10963                               100.0 * (float) (++cur) / (float) max, ino);
10964        }
10965        end_problem_latch(ctx, PR_LATCH_OPTIMIZE_DIR);
10966        if (!all_dirs)
10967                ext2fs_u32_list_iterate_end(iter);
10968
10969        ext2fs_u32_list_free(ctx->dirs_to_hash);
10970        ctx->dirs_to_hash = 0;
10971}
10972
10973/*
10974 * linux/fs/revoke.c
10975 *
10976 * Journal revoke routines for the generic filesystem journaling code;
10977 * part of the ext2fs journaling system.
10978 *
10979 * Revoke is the mechanism used to prevent old log records for deleted
10980 * metadata from being replayed on top of newer data using the same
10981 * blocks.  The revoke mechanism is used in two separate places:
10982 *
10983 * + Commit: during commit we write the entire list of the current
10984 *   transaction's revoked blocks to the journal
10985 *
10986 * + Recovery: during recovery we record the transaction ID of all
10987 *   revoked blocks.  If there are multiple revoke records in the log
10988 *   for a single block, only the last one counts, and if there is a log
10989 *   entry for a block beyond the last revoke, then that log entry still
10990 *   gets replayed.
10991 *
10992 * We can get interactions between revokes and new log data within a
10993 * single transaction:
10994 *
10995 * Block is revoked and then journaled:
10996 *   The desired end result is the journaling of the new block, so we
10997 *   cancel the revoke before the transaction commits.
10998 *
10999 * Block is journaled and then revoked:
11000 *   The revoke must take precedence over the write of the block, so we
11001 *   need either to cancel the journal entry or to write the revoke
11002 *   later in the log than the log block.  In this case, we choose the
11003 *   latter: journaling a block cancels any revoke record for that block
11004 *   in the current transaction, so any revoke for that block in the
11005 *   transaction must have happened after the block was journaled and so
11006 *   the revoke must take precedence.
11007 *
11008 * Block is revoked and then written as data:
11009 *   The data write is allowed to succeed, but the revoke is _not_
11010 *   cancelled.  We still need to prevent old log records from
11011 *   overwriting the new data.  We don't even need to clear the revoke
11012 *   bit here.
11013 *
11014 * Revoke information on buffers is a tri-state value:
11015 *
11016 * RevokeValid clear:   no cached revoke status, need to look it up
11017 * RevokeValid set, Revoked clear:
11018 *                      buffer has not been revoked, and cancel_revoke
11019 *                      need do nothing.
11020 * RevokeValid set, Revoked set:
11021 *                      buffer has been revoked.
11022 */
11023
11024static kmem_cache_t *revoke_record_cache;
11025static kmem_cache_t *revoke_table_cache;
11026
11027/* Each revoke record represents one single revoked block.  During
11028   journal replay, this involves recording the transaction ID of the
11029   last transaction to revoke this block. */
11030
11031struct jbd_revoke_record_s
11032{
11033        struct list_head  hash;
11034        tid_t             sequence;     /* Used for recovery only */
11035        unsigned long     blocknr;
11036};
11037
11038
11039/* The revoke table is just a simple hash table of revoke records. */
11040struct jbd_revoke_table_s
11041{
11042        /* It is conceivable that we might want a larger hash table
11043         * for recovery.  Must be a power of two. */
11044        int               hash_size;
11045        int               hash_shift;
11046        struct list_head *hash_table;
11047};
11048
11049
11050/* Utility functions to maintain the revoke table */
11051
11052/* Borrowed from buffer.c: this is a tried and tested block hash function */
11053static int hash(journal_t *journal, unsigned long block)
11054{
11055        struct jbd_revoke_table_s *table = journal->j_revoke;
11056        int hash_shift = table->hash_shift;
11057
11058        return ((block << (hash_shift - 6)) ^
11059                (block >> 13) ^
11060                (block << (hash_shift - 12))) & (table->hash_size - 1);
11061}
11062
11063static int insert_revoke_hash(journal_t *journal, unsigned long blocknr,
11064                              tid_t seq)
11065{
11066        struct list_head *hash_list;
11067        struct jbd_revoke_record_s *record;
11068
11069        record = kmem_cache_alloc(revoke_record_cache, GFP_NOFS);
11070        if (!record)
11071                goto oom;
11072
11073        record->sequence = seq;
11074        record->blocknr = blocknr;
11075        hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11076        list_add(&record->hash, hash_list);
11077        return 0;
11078
11079oom:
11080        return -ENOMEM;
11081}
11082
11083/* Find a revoke record in the journal's hash table. */
11084
11085static struct jbd_revoke_record_s *find_revoke_record(journal_t *journal,
11086                                                      unsigned long blocknr)
11087{
11088        struct list_head *hash_list;
11089        struct jbd_revoke_record_s *record;
11090
11091        hash_list = &journal->j_revoke->hash_table[hash(journal, blocknr)];
11092
11093        record = (struct jbd_revoke_record_s *) hash_list->next;
11094        while (&(record->hash) != hash_list) {
11095                if (record->blocknr == blocknr)
11096                        return record;
11097                record = (struct jbd_revoke_record_s *) record->hash.next;
11098        }
11099        return NULL;
11100}
11101
11102int journal_init_revoke_caches(void)
11103{
11104        revoke_record_cache = do_cache_create(sizeof(struct jbd_revoke_record_s));
11105        if (revoke_record_cache == 0)
11106                return -ENOMEM;
11107
11108        revoke_table_cache = do_cache_create(sizeof(struct jbd_revoke_table_s));
11109        if (revoke_table_cache == 0) {
11110                do_cache_destroy(revoke_record_cache);
11111                revoke_record_cache = NULL;
11112                return -ENOMEM;
11113        }
11114        return 0;
11115}
11116
11117void journal_destroy_revoke_caches(void)
11118{
11119        do_cache_destroy(revoke_record_cache);
11120        revoke_record_cache = 0;
11121        do_cache_destroy(revoke_table_cache);
11122        revoke_table_cache = 0;
11123}
11124
11125/* Initialise the revoke table for a given journal to a given size. */
11126
11127int journal_init_revoke(journal_t *journal, int hash_size)
11128{
11129        int shift, tmp;
11130
11131        journal->j_revoke = kmem_cache_alloc(revoke_table_cache, GFP_KERNEL);
11132        if (!journal->j_revoke)
11133                return -ENOMEM;
11134
11135        /* Check that the hash_size is a power of two */
11136        journal->j_revoke->hash_size = hash_size;
11137
11138        shift = 0;
11139        tmp = hash_size;
11140        while ((tmp >>= 1UL) != 0UL)
11141                shift++;
11142        journal->j_revoke->hash_shift = shift;
11143
11144        journal->j_revoke->hash_table = xmalloc(hash_size * sizeof(struct list_head));
11145
11146        for (tmp = 0; tmp < hash_size; tmp++)
11147                INIT_LIST_HEAD(&journal->j_revoke->hash_table[tmp]);
11148
11149        return 0;
11150}
11151
11152/* Destoy a journal's revoke table.  The table must already be empty! */
11153
11154void journal_destroy_revoke(journal_t *journal)
11155{
11156        struct jbd_revoke_table_s *table;
11157        struct list_head *hash_list;
11158        int i;
11159
11160        table = journal->j_revoke;
11161        if (!table)
11162                return;
11163
11164        for (i=0; i<table->hash_size; i++) {
11165                hash_list = &table->hash_table[i];
11166        }
11167
11168        free(table->hash_table);
11169        free(table);
11170        journal->j_revoke = NULL;
11171}
11172
11173/*
11174 * Revoke support for recovery.
11175 *
11176 * Recovery needs to be able to:
11177 *
11178 *  record all revoke records, including the tid of the latest instance
11179 *  of each revoke in the journal
11180 *
11181 *  check whether a given block in a given transaction should be replayed
11182 *  (ie. has not been revoked by a revoke record in that or a subsequent
11183 *  transaction)
11184 *
11185 *  empty the revoke table after recovery.
11186 */
11187
11188/*
11189 * First, setting revoke records.  We create a new revoke record for
11190 * every block ever revoked in the log as we scan it for recovery, and
11191 * we update the existing records if we find multiple revokes for a
11192 * single block.
11193 */
11194
11195int journal_set_revoke(journal_t *journal, unsigned long blocknr,
11196                       tid_t sequence)
11197{
11198        struct jbd_revoke_record_s *record;
11199
11200        record = find_revoke_record(journal, blocknr);
11201        if (record) {
11202                /* If we have multiple occurences, only record the
11203                 * latest sequence number in the hashed record */
11204                if (tid_gt(sequence, record->sequence))
11205                        record->sequence = sequence;
11206                return 0;
11207        }
11208        return insert_revoke_hash(journal, blocknr, sequence);
11209}
11210
11211/*
11212 * Test revoke records.  For a given block referenced in the log, has
11213 * that block been revoked?  A revoke record with a given transaction
11214 * sequence number revokes all blocks in that transaction and earlier
11215 * ones, but later transactions still need replayed.
11216 */
11217
11218int journal_test_revoke(journal_t *journal, unsigned long blocknr,
11219                        tid_t sequence)
11220{
11221        struct jbd_revoke_record_s *record;
11222
11223        record = find_revoke_record(journal, blocknr);
11224        if (!record)
11225                return 0;
11226        if (tid_gt(sequence, record->sequence))
11227                return 0;
11228        return 1;
11229}
11230
11231/*
11232 * Finally, once recovery is over, we need to clear the revoke table so
11233 * that it can be reused by the running filesystem.
11234 */
11235
11236void journal_clear_revoke(journal_t *journal)
11237{
11238        int i;
11239        struct list_head *hash_list;
11240        struct jbd_revoke_record_s *record;
11241        struct jbd_revoke_table_s *revoke_var;
11242
11243        revoke_var = journal->j_revoke;
11244
11245        for (i = 0; i < revoke_var->hash_size; i++) {
11246                hash_list = &revoke_var->hash_table[i];
11247                while (!list_empty(hash_list)) {
11248                        record = (struct jbd_revoke_record_s*) hash_list->next;
11249                        list_del(&record->hash);
11250                        free(record);
11251                }
11252        }
11253}
11254
11255/*
11256 * e2fsck.c - superblock checks
11257 */
11258
11259#define MIN_CHECK 1
11260#define MAX_CHECK 2
11261
11262static void check_super_value(e2fsck_t ctx, const char *descr,
11263                              unsigned long value, int flags,
11264                              unsigned long min_val, unsigned long max_val)
11265{
11266        struct          problem_context pctx;
11267
11268        if (((flags & MIN_CHECK) && (value < min_val)) ||
11269            ((flags & MAX_CHECK) && (value > max_val))) {
11270                clear_problem_context(&pctx);
11271                pctx.num = value;
11272                pctx.str = descr;
11273                fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11274                ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11275        }
11276}
11277
11278/*
11279 * This routine may get stubbed out in special compilations of the
11280 * e2fsck code..
11281 */
11282#ifndef EXT2_SPECIAL_DEVICE_SIZE
11283static errcode_t e2fsck_get_device_size(e2fsck_t ctx)
11284{
11285        return (ext2fs_get_device_size(ctx->filesystem_name,
11286                                       EXT2_BLOCK_SIZE(ctx->fs->super),
11287                                       &ctx->num_blocks));
11288}
11289#endif
11290
11291/*
11292 * helper function to release an inode
11293 */
11294struct process_block_struct {
11295        e2fsck_t        ctx;
11296        char            *buf;
11297        struct problem_context *pctx;
11298        int             truncating;
11299        int             truncate_offset;
11300        e2_blkcnt_t     truncate_block;
11301        int             truncated_blocks;
11302        int             abort;
11303        errcode_t       errcode;
11304};
11305
11306static int release_inode_block(ext2_filsys fs, blk_t *block_nr,
11307                               e2_blkcnt_t blockcnt,
11308                               blk_t    ref_blk FSCK_ATTR((unused)),
11309                               int      ref_offset FSCK_ATTR((unused)),
11310                               void *priv_data)
11311{
11312        struct process_block_struct *pb;
11313        e2fsck_t                ctx;
11314        struct problem_context  *pctx;
11315        blk_t                   blk = *block_nr;
11316        int                     retval = 0;
11317
11318        pb = (struct process_block_struct *) priv_data;
11319        ctx = pb->ctx;
11320        pctx = pb->pctx;
11321
11322        pctx->blk = blk;
11323        pctx->blkcount = blockcnt;
11324
11325        if (HOLE_BLKADDR(blk))
11326                return 0;
11327
11328        if ((blk < fs->super->s_first_data_block) ||
11329            (blk >= fs->super->s_blocks_count)) {
11330                fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_BLOCK_NUM, pctx);
11331        return_abort:
11332                pb->abort = 1;
11333                return BLOCK_ABORT;
11334        }
11335
11336        if (!ext2fs_test_block_bitmap(fs->block_map, blk)) {
11337                fix_problem(ctx, PR_0_ORPHAN_ALREADY_CLEARED_BLOCK, pctx);
11338                goto return_abort;
11339        }
11340
11341        /*
11342         * If we are deleting an orphan, then we leave the fields alone.
11343         * If we are truncating an orphan, then update the inode fields
11344         * and clean up any partial block data.
11345         */
11346        if (pb->truncating) {
11347                /*
11348                 * We only remove indirect blocks if they are
11349                 * completely empty.
11350                 */
11351                if (blockcnt < 0) {
11352                        int     i, limit;
11353                        blk_t   *bp;
11354
11355                        pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11356                                                        pb->buf);
11357                        if (pb->errcode)
11358                                goto return_abort;
11359
11360                        limit = fs->blocksize >> 2;
11361                        for (i = 0, bp = (blk_t *) pb->buf;
11362                             i < limit;  i++, bp++)
11363                                if (*bp)
11364                                        return 0;
11365                }
11366                /*
11367                 * We don't remove direct blocks until we've reached
11368                 * the truncation block.
11369                 */
11370                if (blockcnt >= 0 && blockcnt < pb->truncate_block)
11371                        return 0;
11372                /*
11373                 * If part of the last block needs truncating, we do
11374                 * it here.
11375                 */
11376                if ((blockcnt == pb->truncate_block) && pb->truncate_offset) {
11377                        pb->errcode = io_channel_read_blk(fs->io, blk, 1,
11378                                                        pb->buf);
11379                        if (pb->errcode)
11380                                goto return_abort;
11381                        memset(pb->buf + pb->truncate_offset, 0,
11382                               fs->blocksize - pb->truncate_offset);
11383                        pb->errcode = io_channel_write_blk(fs->io, blk, 1,
11384                                                         pb->buf);
11385                        if (pb->errcode)
11386                                goto return_abort;
11387                }
11388                pb->truncated_blocks++;
11389                *block_nr = 0;
11390                retval |= BLOCK_CHANGED;
11391        }
11392
11393        ext2fs_block_alloc_stats(fs, blk, -1);
11394        return retval;
11395}
11396
11397/*
11398 * This function releases an inode.  Returns 1 if an inconsistency was
11399 * found.  If the inode has a link count, then it is being truncated and
11400 * not deleted.
11401 */
11402static int release_inode_blocks(e2fsck_t ctx, ext2_ino_t ino,
11403                                struct ext2_inode *inode, char *block_buf,
11404                                struct problem_context *pctx)
11405{
11406        struct process_block_struct     pb;
11407        ext2_filsys                     fs = ctx->fs;
11408        errcode_t                       retval;
11409        __u32                           count;
11410
11411        if (!ext2fs_inode_has_valid_blocks(inode))
11412                return 0;
11413
11414        pb.buf = block_buf + 3 * ctx->fs->blocksize;
11415        pb.ctx = ctx;
11416        pb.abort = 0;
11417        pb.errcode = 0;
11418        pb.pctx = pctx;
11419        if (inode->i_links_count) {
11420                pb.truncating = 1;
11421                pb.truncate_block = (e2_blkcnt_t)
11422                        ((((long long)inode->i_size_high << 32) +
11423                          inode->i_size + fs->blocksize - 1) /
11424                         fs->blocksize);
11425                pb.truncate_offset = inode->i_size % fs->blocksize;
11426        } else {
11427                pb.truncating = 0;
11428                pb.truncate_block = 0;
11429                pb.truncate_offset = 0;
11430        }
11431        pb.truncated_blocks = 0;
11432        retval = ext2fs_block_iterate2(fs, ino, BLOCK_FLAG_DEPTH_TRAVERSE,
11433                                      block_buf, release_inode_block, &pb);
11434        if (retval) {
11435                bb_error_msg(_("while calling ext2fs_block_iterate for inode %d"),
11436                        ino);
11437                return 1;
11438        }
11439        if (pb.abort)
11440                return 1;
11441
11442        /* Refresh the inode since ext2fs_block_iterate may have changed it */
11443        e2fsck_read_inode(ctx, ino, inode, "release_inode_blocks");
11444
11445        if (pb.truncated_blocks)
11446                inode->i_blocks -= pb.truncated_blocks *
11447                        (fs->blocksize / 512);
11448
11449        if (inode->i_file_acl) {
11450                retval = ext2fs_adjust_ea_refcount(fs, inode->i_file_acl,
11451                                                   block_buf, -1, &count);
11452                if (retval == EXT2_ET_BAD_EA_BLOCK_NUM) {
11453                        retval = 0;
11454                        count = 1;
11455                }
11456                if (retval) {
11457                        bb_error_msg(_("while calling ext2fs_adjust_ea_refocunt for inode %d"),
11458                                ino);
11459                        return 1;
11460                }
11461                if (count == 0)
11462                        ext2fs_block_alloc_stats(fs, inode->i_file_acl, -1);
11463                inode->i_file_acl = 0;
11464        }
11465        return 0;
11466}
11467
11468/*
11469 * This function releases all of the orphan inodes.  It returns 1 if
11470 * it hit some error, and 0 on success.
11471 */
11472static int release_orphan_inodes(e2fsck_t ctx)
11473{
11474        ext2_filsys fs = ctx->fs;
11475        ext2_ino_t      ino, next_ino;
11476        struct ext2_inode inode;
11477        struct problem_context pctx;
11478        char *block_buf;
11479
11480        if ((ino = fs->super->s_last_orphan) == 0)
11481                return 0;
11482
11483        /*
11484         * Win or lose, we won't be using the head of the orphan inode
11485         * list again.
11486         */
11487        fs->super->s_last_orphan = 0;
11488        ext2fs_mark_super_dirty(fs);
11489
11490        /*
11491         * If the filesystem contains errors, don't run the orphan
11492         * list, since the orphan list can't be trusted; and we're
11493         * going to be running a full e2fsck run anyway...
11494         */
11495        if (fs->super->s_state & EXT2_ERROR_FS)
11496                return 0;
11497
11498        if ((ino < EXT2_FIRST_INODE(fs->super)) ||
11499            (ino > fs->super->s_inodes_count)) {
11500                clear_problem_context(&pctx);
11501                pctx.ino = ino;
11502                fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_HEAD_INODE, &pctx);
11503                return 1;
11504        }
11505
11506        block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
11507                                                    "block iterate buffer");
11508        e2fsck_read_bitmaps(ctx);
11509
11510        while (ino) {
11511                e2fsck_read_inode(ctx, ino, &inode, "release_orphan_inodes");
11512                clear_problem_context(&pctx);
11513                pctx.ino = ino;
11514                pctx.inode = &inode;
11515                pctx.str = inode.i_links_count ? _("Truncating") :
11516                        _("Clearing");
11517
11518                fix_problem(ctx, PR_0_ORPHAN_CLEAR_INODE, &pctx);
11519
11520                next_ino = inode.i_dtime;
11521                if (next_ino &&
11522                    ((next_ino < EXT2_FIRST_INODE(fs->super)) ||
11523                     (next_ino > fs->super->s_inodes_count))) {
11524                        pctx.ino = next_ino;
11525                        fix_problem(ctx, PR_0_ORPHAN_ILLEGAL_INODE, &pctx);
11526                        goto return_abort;
11527                }
11528
11529                if (release_inode_blocks(ctx, ino, &inode, block_buf, &pctx))
11530                        goto return_abort;
11531
11532                if (!inode.i_links_count) {
11533                        ext2fs_inode_alloc_stats2(fs, ino, -1,
11534                                                  LINUX_S_ISDIR(inode.i_mode));
11535                        inode.i_dtime = time(NULL);
11536                } else {
11537                        inode.i_dtime = 0;
11538                }
11539                e2fsck_write_inode(ctx, ino, &inode, "delete_file");
11540                ino = next_ino;
11541        }
11542        ext2fs_free_mem(&block_buf);
11543        return 0;
11544return_abort:
11545        ext2fs_free_mem(&block_buf);
11546        return 1;
11547}
11548
11549/*
11550 * Check the resize inode to make sure it is sane.  We check both for
11551 * the case where on-line resizing is not enabled (in which case the
11552 * resize inode should be cleared) as well as the case where on-line
11553 * resizing is enabled.
11554 */
11555static void check_resize_inode(e2fsck_t ctx)
11556{
11557        ext2_filsys fs = ctx->fs;
11558        struct ext2_inode inode;
11559        struct problem_context  pctx;
11560        int             i, j, gdt_off, ind_off;
11561        blk_t           blk, pblk, expect;
11562        __u32           *dind_buf = 0, *ind_buf;
11563        errcode_t       retval;
11564
11565        clear_problem_context(&pctx);
11566
11567        /*
11568         * If the resize inode feature isn't set, then
11569         * s_reserved_gdt_blocks must be zero.
11570         */
11571        if (!(fs->super->s_feature_compat &
11572              EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11573                if (fs->super->s_reserved_gdt_blocks) {
11574                        pctx.num = fs->super->s_reserved_gdt_blocks;
11575                        if (fix_problem(ctx, PR_0_NONZERO_RESERVED_GDT_BLOCKS,
11576                                        &pctx)) {
11577                                fs->super->s_reserved_gdt_blocks = 0;
11578                                ext2fs_mark_super_dirty(fs);
11579                        }
11580                }
11581        }
11582
11583        /* Read the resize inode */
11584        pctx.ino = EXT2_RESIZE_INO;
11585        retval = ext2fs_read_inode(fs, EXT2_RESIZE_INO, &inode);
11586        if (retval) {
11587                if (fs->super->s_feature_compat &
11588                    EXT2_FEATURE_COMPAT_RESIZE_INODE)
11589                        ctx->flags |= E2F_FLAG_RESIZE_INODE;
11590                return;
11591        }
11592
11593        /*
11594         * If the resize inode feature isn't set, check to make sure
11595         * the resize inode is cleared; then we're done.
11596         */
11597        if (!(fs->super->s_feature_compat &
11598              EXT2_FEATURE_COMPAT_RESIZE_INODE)) {
11599                for (i=0; i < EXT2_N_BLOCKS; i++) {
11600                        if (inode.i_block[i])
11601                                break;
11602                }
11603                if ((i < EXT2_N_BLOCKS) &&
11604                    fix_problem(ctx, PR_0_CLEAR_RESIZE_INODE, &pctx)) {
11605                        memset(&inode, 0, sizeof(inode));
11606                        e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11607                                           "clear_resize");
11608                }
11609                return;
11610        }
11611
11612        /*
11613         * The resize inode feature is enabled; check to make sure the
11614         * only block in use is the double indirect block
11615         */
11616        blk = inode.i_block[EXT2_DIND_BLOCK];
11617        for (i=0; i < EXT2_N_BLOCKS; i++) {
11618                if (i != EXT2_DIND_BLOCK && inode.i_block[i])
11619                        break;
11620        }
11621        if ((i < EXT2_N_BLOCKS) || !blk || !inode.i_links_count ||
11622            !(inode.i_mode & LINUX_S_IFREG) ||
11623            (blk < fs->super->s_first_data_block ||
11624             blk >= fs->super->s_blocks_count)) {
11625        resize_inode_invalid:
11626                if (fix_problem(ctx, PR_0_RESIZE_INODE_INVALID, &pctx)) {
11627                        memset(&inode, 0, sizeof(inode));
11628                        e2fsck_write_inode(ctx, EXT2_RESIZE_INO, &inode,
11629                                           "clear_resize");
11630                        ctx->flags |= E2F_FLAG_RESIZE_INODE;
11631                }
11632                if (!(ctx->options & E2F_OPT_READONLY)) {
11633                        fs->super->s_state &= ~EXT2_VALID_FS;
11634                        ext2fs_mark_super_dirty(fs);
11635                }
11636                goto cleanup;
11637        }
11638        dind_buf = (__u32 *) e2fsck_allocate_memory(ctx, fs->blocksize * 2,
11639                                                    "resize dind buffer");
11640        ind_buf = (__u32 *) ((char *) dind_buf + fs->blocksize);
11641
11642        retval = ext2fs_read_ind_block(fs, blk, dind_buf);
11643        if (retval)
11644                goto resize_inode_invalid;
11645
11646        gdt_off = fs->desc_blocks;
11647        pblk = fs->super->s_first_data_block + 1 + fs->desc_blocks;
11648        for (i = 0; i < fs->super->s_reserved_gdt_blocks / 4;
11649             i++, gdt_off++, pblk++) {
11650                gdt_off %= fs->blocksize/4;
11651                if (dind_buf[gdt_off] != pblk)
11652                        goto resize_inode_invalid;
11653                retval = ext2fs_read_ind_block(fs, pblk, ind_buf);
11654                if (retval)
11655                        goto resize_inode_invalid;
11656                ind_off = 0;
11657                for (j = 1; j < fs->group_desc_count; j++) {
11658                        if (!ext2fs_bg_has_super(fs, j))
11659                                continue;
11660                        expect = pblk + (j * fs->super->s_blocks_per_group);
11661                        if (ind_buf[ind_off] != expect)
11662                                goto resize_inode_invalid;
11663                        ind_off++;
11664                }
11665        }
11666
11667cleanup:
11668        ext2fs_free_mem(&dind_buf);
11669
11670 }
11671
11672static void check_super_block(e2fsck_t ctx)
11673{
11674        ext2_filsys fs = ctx->fs;
11675        blk_t   first_block, last_block;
11676        struct ext2_super_block *sb = fs->super;
11677        struct ext2_group_desc *gd;
11678        blk_t   blocks_per_group = fs->super->s_blocks_per_group;
11679        blk_t   bpg_max;
11680        int     inodes_per_block;
11681        int     ipg_max;
11682        int     inode_size;
11683        dgrp_t  i;
11684        blk_t   should_be;
11685        struct problem_context  pctx;
11686        __u32   free_blocks = 0, free_inodes = 0;
11687
11688        inodes_per_block = EXT2_INODES_PER_BLOCK(fs->super);
11689        ipg_max = inodes_per_block * (blocks_per_group - 4);
11690        if (ipg_max > EXT2_MAX_INODES_PER_GROUP(sb))
11691                ipg_max = EXT2_MAX_INODES_PER_GROUP(sb);
11692        bpg_max = 8 * EXT2_BLOCK_SIZE(sb);
11693        if (bpg_max > EXT2_MAX_BLOCKS_PER_GROUP(sb))
11694                bpg_max = EXT2_MAX_BLOCKS_PER_GROUP(sb);
11695
11696        ctx->invalid_inode_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11697                 sizeof(int) * fs->group_desc_count, "invalid_inode_bitmap");
11698        ctx->invalid_block_bitmap_flag = (int *) e2fsck_allocate_memory(ctx,
11699                 sizeof(int) * fs->group_desc_count, "invalid_block_bitmap");
11700        ctx->invalid_inode_table_flag = (int *) e2fsck_allocate_memory(ctx,
11701                sizeof(int) * fs->group_desc_count, "invalid_inode_table");
11702
11703        clear_problem_context(&pctx);
11704
11705        /*
11706         * Verify the super block constants...
11707         */
11708        check_super_value(ctx, "inodes_count", sb->s_inodes_count,
11709                          MIN_CHECK, 1, 0);
11710        check_super_value(ctx, "blocks_count", sb->s_blocks_count,
11711                          MIN_CHECK, 1, 0);
11712        check_super_value(ctx, "first_data_block", sb->s_first_data_block,
11713                          MAX_CHECK, 0, sb->s_blocks_count);
11714        check_super_value(ctx, "log_block_size", sb->s_log_block_size,
11715                          MIN_CHECK | MAX_CHECK, 0,
11716                          EXT2_MAX_BLOCK_LOG_SIZE - EXT2_MIN_BLOCK_LOG_SIZE);
11717        check_super_value(ctx, "log_frag_size", sb->s_log_frag_size,
11718                          MIN_CHECK | MAX_CHECK, 0, sb->s_log_block_size);
11719        check_super_value(ctx, "frags_per_group", sb->s_frags_per_group,
11720                          MIN_CHECK | MAX_CHECK, sb->s_blocks_per_group,
11721                          bpg_max);
11722        check_super_value(ctx, "blocks_per_group", sb->s_blocks_per_group,
11723                          MIN_CHECK | MAX_CHECK, 8, bpg_max);
11724        check_super_value(ctx, "inodes_per_group", sb->s_inodes_per_group,
11725                          MIN_CHECK | MAX_CHECK, inodes_per_block, ipg_max);
11726        check_super_value(ctx, "r_blocks_count", sb->s_r_blocks_count,
11727                          MAX_CHECK, 0, sb->s_blocks_count / 2);
11728        check_super_value(ctx, "reserved_gdt_blocks",
11729                          sb->s_reserved_gdt_blocks, MAX_CHECK, 0,
11730                          fs->blocksize/4);
11731        inode_size = EXT2_INODE_SIZE(sb);
11732        check_super_value(ctx, "inode_size",
11733                          inode_size, MIN_CHECK | MAX_CHECK,
11734                          EXT2_GOOD_OLD_INODE_SIZE, fs->blocksize);
11735        if (inode_size & (inode_size - 1)) {
11736                pctx.num = inode_size;
11737                pctx.str = "inode_size";
11738                fix_problem(ctx, PR_0_MISC_CORRUPT_SUPER, &pctx);
11739                ctx->flags |= E2F_FLAG_ABORT; /* never get here! */
11740                return;
11741        }
11742
11743        if (!ctx->num_blocks) {
11744                pctx.errcode = e2fsck_get_device_size(ctx);
11745                if (pctx.errcode && pctx.errcode != EXT2_ET_UNIMPLEMENTED) {
11746                        fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
11747                        ctx->flags |= E2F_FLAG_ABORT;
11748                        return;
11749                }
11750                if ((pctx.errcode != EXT2_ET_UNIMPLEMENTED) &&
11751                    (ctx->num_blocks < sb->s_blocks_count)) {
11752                        pctx.blk = sb->s_blocks_count;
11753                        pctx.blk2 = ctx->num_blocks;
11754                        if (fix_problem(ctx, PR_0_FS_SIZE_WRONG, &pctx)) {
11755                                ctx->flags |= E2F_FLAG_ABORT;
11756                                return;
11757                        }
11758                }
11759        }
11760
11761        if (sb->s_log_block_size != (__u32) sb->s_log_frag_size) {
11762                pctx.blk = EXT2_BLOCK_SIZE(sb);
11763                pctx.blk2 = EXT2_FRAG_SIZE(sb);
11764                fix_problem(ctx, PR_0_NO_FRAGMENTS, &pctx);
11765                ctx->flags |= E2F_FLAG_ABORT;
11766                return;
11767        }
11768
11769        should_be = sb->s_frags_per_group >>
11770                (sb->s_log_block_size - sb->s_log_frag_size);
11771        if (sb->s_blocks_per_group != should_be) {
11772                pctx.blk = sb->s_blocks_per_group;
11773                pctx.blk2 = should_be;
11774                fix_problem(ctx, PR_0_BLOCKS_PER_GROUP, &pctx);
11775                ctx->flags |= E2F_FLAG_ABORT;
11776                return;
11777        }
11778
11779        should_be = (sb->s_log_block_size == 0) ? 1 : 0;
11780        if (sb->s_first_data_block != should_be) {
11781                pctx.blk = sb->s_first_data_block;
11782                pctx.blk2 = should_be;
11783                fix_problem(ctx, PR_0_FIRST_DATA_BLOCK, &pctx);
11784                ctx->flags |= E2F_FLAG_ABORT;
11785                return;
11786        }
11787
11788        should_be = sb->s_inodes_per_group * fs->group_desc_count;
11789        if (sb->s_inodes_count != should_be) {
11790                pctx.ino = sb->s_inodes_count;
11791                pctx.ino2 = should_be;
11792                if (fix_problem(ctx, PR_0_INODE_COUNT_WRONG, &pctx)) {
11793                        sb->s_inodes_count = should_be;
11794                        ext2fs_mark_super_dirty(fs);
11795                }
11796        }
11797
11798        /*
11799         * Verify the group descriptors....
11800         */
11801        first_block =  sb->s_first_data_block;
11802        last_block = first_block + blocks_per_group;
11803
11804        for (i = 0, gd=fs->group_desc; i < fs->group_desc_count; i++, gd++) {
11805                pctx.group = i;
11806
11807                if (i == fs->group_desc_count - 1)
11808                        last_block = sb->s_blocks_count;
11809                if ((gd->bg_block_bitmap < first_block) ||
11810                    (gd->bg_block_bitmap >= last_block)) {
11811                        pctx.blk = gd->bg_block_bitmap;
11812                        if (fix_problem(ctx, PR_0_BB_NOT_GROUP, &pctx))
11813                                gd->bg_block_bitmap = 0;
11814                }
11815                if (gd->bg_block_bitmap == 0) {
11816                        ctx->invalid_block_bitmap_flag[i]++;
11817                        ctx->invalid_bitmaps++;
11818                }
11819                if ((gd->bg_inode_bitmap < first_block) ||
11820                    (gd->bg_inode_bitmap >= last_block)) {
11821                        pctx.blk = gd->bg_inode_bitmap;
11822                        if (fix_problem(ctx, PR_0_IB_NOT_GROUP, &pctx))
11823                                gd->bg_inode_bitmap = 0;
11824                }
11825                if (gd->bg_inode_bitmap == 0) {
11826                        ctx->invalid_inode_bitmap_flag[i]++;
11827                        ctx->invalid_bitmaps++;
11828                }
11829                if ((gd->bg_inode_table < first_block) ||
11830                    ((gd->bg_inode_table +
11831                      fs->inode_blocks_per_group - 1) >= last_block)) {
11832                        pctx.blk = gd->bg_inode_table;
11833                        if (fix_problem(ctx, PR_0_ITABLE_NOT_GROUP, &pctx))
11834                                gd->bg_inode_table = 0;
11835                }
11836                if (gd->bg_inode_table == 0) {
11837                        ctx->invalid_inode_table_flag[i]++;
11838                        ctx->invalid_bitmaps++;
11839                }
11840                free_blocks += gd->bg_free_blocks_count;
11841                free_inodes += gd->bg_free_inodes_count;
11842                first_block += sb->s_blocks_per_group;
11843                last_block += sb->s_blocks_per_group;
11844
11845                if ((gd->bg_free_blocks_count > sb->s_blocks_per_group) ||
11846                    (gd->bg_free_inodes_count > sb->s_inodes_per_group) ||
11847                    (gd->bg_used_dirs_count > sb->s_inodes_per_group))
11848                        ext2fs_unmark_valid(fs);
11849
11850        }
11851
11852        /*
11853         * Update the global counts from the block group counts.  This
11854         * is needed for an experimental patch which eliminates
11855         * locking the entire filesystem when allocating blocks or
11856         * inodes; if the filesystem is not unmounted cleanly, the
11857         * global counts may not be accurate.
11858         */
11859        if ((free_blocks != sb->s_free_blocks_count) ||
11860            (free_inodes != sb->s_free_inodes_count)) {
11861                if (ctx->options & E2F_OPT_READONLY)
11862                        ext2fs_unmark_valid(fs);
11863                else {
11864                        sb->s_free_blocks_count = free_blocks;
11865                        sb->s_free_inodes_count = free_inodes;
11866                        ext2fs_mark_super_dirty(fs);
11867                }
11868        }
11869
11870        if ((sb->s_free_blocks_count > sb->s_blocks_count) ||
11871            (sb->s_free_inodes_count > sb->s_inodes_count))
11872                ext2fs_unmark_valid(fs);
11873
11874
11875        /*
11876         * If we have invalid bitmaps, set the error state of the
11877         * filesystem.
11878         */
11879        if (ctx->invalid_bitmaps && !(ctx->options & E2F_OPT_READONLY)) {
11880                sb->s_state &= ~EXT2_VALID_FS;
11881                ext2fs_mark_super_dirty(fs);
11882        }
11883
11884        clear_problem_context(&pctx);
11885
11886        /*
11887         * If the UUID field isn't assigned, assign it.
11888         */
11889        if (!(ctx->options & E2F_OPT_READONLY) && uuid_is_null(sb->s_uuid)) {
11890                if (fix_problem(ctx, PR_0_ADD_UUID, &pctx)) {
11891                        uuid_generate(sb->s_uuid);
11892                        ext2fs_mark_super_dirty(fs);
11893                        fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
11894                }
11895        }
11896
11897        /* FIXME - HURD support?
11898         * For the Hurd, check to see if the filetype option is set,
11899         * since it doesn't support it.
11900         */
11901        if (!(ctx->options & E2F_OPT_READONLY) &&
11902            fs->super->s_creator_os == EXT2_OS_HURD &&
11903            (fs->super->s_feature_incompat &
11904             EXT2_FEATURE_INCOMPAT_FILETYPE)) {
11905                if (fix_problem(ctx, PR_0_HURD_CLEAR_FILETYPE, &pctx)) {
11906                        fs->super->s_feature_incompat &=
11907                                ~EXT2_FEATURE_INCOMPAT_FILETYPE;
11908                        ext2fs_mark_super_dirty(fs);
11909
11910                }
11911        }
11912
11913        /*
11914         * If we have any of the compatibility flags set, we need to have a
11915         * revision 1 filesystem.  Most kernels will not check the flags on
11916         * a rev 0 filesystem and we may have corruption issues because of
11917         * the incompatible changes to the filesystem.
11918         */
11919        if (!(ctx->options & E2F_OPT_READONLY) &&
11920            fs->super->s_rev_level == EXT2_GOOD_OLD_REV &&
11921            (fs->super->s_feature_compat ||
11922             fs->super->s_feature_ro_compat ||
11923             fs->super->s_feature_incompat) &&
11924            fix_problem(ctx, PR_0_FS_REV_LEVEL, &pctx)) {
11925                ext2fs_update_dynamic_rev(fs);
11926                ext2fs_mark_super_dirty(fs);
11927        }
11928
11929        check_resize_inode(ctx);
11930
11931        /*
11932         * Clean up any orphan inodes, if present.
11933         */
11934        if (!(ctx->options & E2F_OPT_READONLY) && release_orphan_inodes(ctx)) {
11935                fs->super->s_state &= ~EXT2_VALID_FS;
11936                ext2fs_mark_super_dirty(fs);
11937        }
11938
11939        /*
11940         * Move the ext3 journal file, if necessary.
11941         */
11942        e2fsck_move_ext3_journal(ctx);
11943}
11944
11945/*
11946 * swapfs.c --- byte-swap an ext2 filesystem
11947 */
11948
11949#ifdef ENABLE_SWAPFS
11950
11951struct swap_block_struct {
11952        ext2_ino_t      ino;
11953        int             isdir;
11954        errcode_t       errcode;
11955        char            *dir_buf;
11956        struct ext2_inode *inode;
11957};
11958
11959/*
11960 * This is a helper function for block_iterate.  We mark all of the
11961 * indirect and direct blocks as changed, so that block_iterate will
11962 * write them out.
11963 */
11964static int swap_block(ext2_filsys fs, blk_t *block_nr, int blockcnt,
11965                      void *priv_data)
11966{
11967        errcode_t       retval;
11968
11969        struct swap_block_struct *sb = (struct swap_block_struct *) priv_data;
11970
11971        if (sb->isdir && (blockcnt >= 0) && *block_nr) {
11972                retval = ext2fs_read_dir_block(fs, *block_nr, sb->dir_buf);
11973                if (retval) {
11974                        sb->errcode = retval;
11975                        return BLOCK_ABORT;
11976                }
11977                retval = ext2fs_write_dir_block(fs, *block_nr, sb->dir_buf);
11978                if (retval) {
11979                        sb->errcode = retval;
11980                        return BLOCK_ABORT;
11981                }
11982        }
11983        if (blockcnt >= 0) {
11984                if (blockcnt < EXT2_NDIR_BLOCKS)
11985                        return 0;
11986                return BLOCK_CHANGED;
11987        }
11988        if (blockcnt == BLOCK_COUNT_IND) {
11989                if (*block_nr == sb->inode->i_block[EXT2_IND_BLOCK])
11990                        return 0;
11991                return BLOCK_CHANGED;
11992        }
11993        if (blockcnt == BLOCK_COUNT_DIND) {
11994                if (*block_nr == sb->inode->i_block[EXT2_DIND_BLOCK])
11995                        return 0;
11996                return BLOCK_CHANGED;
11997        }
11998        if (blockcnt == BLOCK_COUNT_TIND) {
11999                if (*block_nr == sb->inode->i_block[EXT2_TIND_BLOCK])
12000                        return 0;
12001                return BLOCK_CHANGED;
12002        }
12003        return BLOCK_CHANGED;
12004}
12005
12006/*
12007 * This function is responsible for byte-swapping all of the indirect,
12008 * block pointers.  It is also responsible for byte-swapping directories.
12009 */
12010static void swap_inode_blocks(e2fsck_t ctx, ext2_ino_t ino, char *block_buf,
12011                              struct ext2_inode *inode)
12012{
12013        errcode_t                       retval;
12014        struct swap_block_struct        sb;
12015
12016        sb.ino = ino;
12017        sb.inode = inode;
12018        sb.dir_buf = block_buf + ctx->fs->blocksize*3;
12019        sb.errcode = 0;
12020        sb.isdir = 0;
12021        if (LINUX_S_ISDIR(inode->i_mode))
12022                sb.isdir = 1;
12023
12024        retval = ext2fs_block_iterate(ctx->fs, ino, 0, block_buf,
12025                                      swap_block, &sb);
12026        if (retval) {
12027                bb_error_msg(_("while calling ext2fs_block_iterate"));
12028                ctx->flags |= E2F_FLAG_ABORT;
12029                return;
12030        }
12031        if (sb.errcode) {
12032                bb_error_msg(_("while calling iterator function"));
12033                ctx->flags |= E2F_FLAG_ABORT;
12034                return;
12035        }
12036}
12037
12038static void swap_inodes(e2fsck_t ctx)
12039{
12040        ext2_filsys fs = ctx->fs;
12041        dgrp_t                  group;
12042        unsigned int            i;
12043        ext2_ino_t              ino = 1;
12044        char                    *buf, *block_buf;
12045        errcode_t               retval;
12046        struct ext2_inode *     inode;
12047
12048        e2fsck_use_inode_shortcuts(ctx, 1);
12049
12050        retval = ext2fs_get_mem(fs->blocksize * fs->inode_blocks_per_group,
12051                                &buf);
12052        if (retval) {
12053                bb_error_msg(_("while allocating inode buffer"));
12054                ctx->flags |= E2F_FLAG_ABORT;
12055                return;
12056        }
12057        block_buf = (char *) e2fsck_allocate_memory(ctx, fs->blocksize * 4,
12058                                                    "block interate buffer");
12059        for (group = 0; group < fs->group_desc_count; group++) {
12060                retval = io_channel_read_blk(fs->io,
12061                      fs->group_desc[group].bg_inode_table,
12062                      fs->inode_blocks_per_group, buf);
12063                if (retval) {
12064                        bb_error_msg(_("while reading inode table (group %d)"),
12065                                group);
12066                        ctx->flags |= E2F_FLAG_ABORT;
12067                        return;
12068                }
12069                inode = (struct ext2_inode *) buf;
12070                for (i=0; i < fs->super->s_inodes_per_group;
12071                     i++, ino++, inode++) {
12072                        ctx->stashed_ino = ino;
12073                        ctx->stashed_inode = inode;
12074
12075                        if (fs->flags & EXT2_FLAG_SWAP_BYTES_READ)
12076                                ext2fs_swap_inode(fs, inode, inode, 0);
12077
12078                        /*
12079                         * Skip deleted files.
12080                         */
12081                        if (inode->i_links_count == 0)
12082                                continue;
12083
12084                        if (LINUX_S_ISDIR(inode->i_mode) ||
12085                            ((inode->i_block[EXT2_IND_BLOCK] ||
12086                              inode->i_block[EXT2_DIND_BLOCK] ||
12087                              inode->i_block[EXT2_TIND_BLOCK]) &&
12088                             ext2fs_inode_has_valid_blocks(inode)))
12089                                swap_inode_blocks(ctx, ino, block_buf, inode);
12090
12091                        if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12092                                return;
12093
12094                        if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12095                                ext2fs_swap_inode(fs, inode, inode, 1);
12096                }
12097                retval = io_channel_write_blk(fs->io,
12098                      fs->group_desc[group].bg_inode_table,
12099                      fs->inode_blocks_per_group, buf);
12100                if (retval) {
12101                        bb_error_msg(_("while writing inode table (group %d)"),
12102                                group);
12103                        ctx->flags |= E2F_FLAG_ABORT;
12104                        return;
12105                }
12106        }
12107        ext2fs_free_mem(&buf);
12108        ext2fs_free_mem(&block_buf);
12109        e2fsck_use_inode_shortcuts(ctx, 0);
12110        ext2fs_flush_icache(fs);
12111}
12112
12113#if defined(__powerpc__) && BB_BIG_ENDIAN
12114/*
12115 * On the PowerPC, the big-endian variant of the ext2 filesystem
12116 * has its bitmaps stored as 32-bit words with bit 0 as the LSB
12117 * of each word.  Thus a bitmap with only bit 0 set would be, as
12118 * a string of bytes, 00 00 00 01 00 ...
12119 * To cope with this, we byte-reverse each word of a bitmap if
12120 * we have a big-endian filesystem, that is, if we are *not*
12121 * byte-swapping other word-sized numbers.
12122 */
12123#define EXT2_BIG_ENDIAN_BITMAPS
12124#endif
12125
12126#ifdef EXT2_BIG_ENDIAN_BITMAPS
12127static void ext2fs_swap_bitmap(ext2fs_generic_bitmap bmap)
12128{
12129        __u32 *p = (__u32 *) bmap->bitmap;
12130        int n, nbytes = (bmap->end - bmap->start + 7) / 8;
12131
12132        for (n = nbytes / sizeof(__u32); n > 0; --n, ++p)
12133                *p = ext2fs_swab32(*p);
12134}
12135#endif
12136
12137
12138#ifdef ENABLE_SWAPFS
12139static void swap_filesys(e2fsck_t ctx)
12140{
12141        ext2_filsys fs = ctx->fs;
12142        if (!(ctx->options & E2F_OPT_PREEN))
12143                printf(_("Pass 0: Doing byte-swap of filesystem\n"));
12144
12145        /* Byte swap */
12146
12147        if (fs->super->s_mnt_count) {
12148                fprintf(stderr, _("%s: the filesystem must be freshly "
12149                        "checked using fsck\n"
12150                        "and not mounted before trying to "
12151                        "byte-swap it.\n"), ctx->device_name);
12152                ctx->flags |= E2F_FLAG_ABORT;
12153                return;
12154        }
12155        if (fs->flags & EXT2_FLAG_SWAP_BYTES) {
12156                fs->flags &= ~(EXT2_FLAG_SWAP_BYTES|
12157                               EXT2_FLAG_SWAP_BYTES_WRITE);
12158                fs->flags |= EXT2_FLAG_SWAP_BYTES_READ;
12159        } else {
12160                fs->flags &= ~EXT2_FLAG_SWAP_BYTES_READ;
12161                fs->flags |= EXT2_FLAG_SWAP_BYTES_WRITE;
12162        }
12163        swap_inodes(ctx);
12164        if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
12165                return;
12166        if (fs->flags & EXT2_FLAG_SWAP_BYTES_WRITE)
12167                fs->flags |= EXT2_FLAG_SWAP_BYTES;
12168        fs->flags &= ~(EXT2_FLAG_SWAP_BYTES_READ|
12169                       EXT2_FLAG_SWAP_BYTES_WRITE);
12170
12171#ifdef EXT2_BIG_ENDIAN_BITMAPS
12172        e2fsck_read_bitmaps(ctx);
12173        ext2fs_swap_bitmap(fs->inode_map);
12174        ext2fs_swap_bitmap(fs->block_map);
12175        fs->flags |= EXT2_FLAG_BB_DIRTY | EXT2_FLAG_IB_DIRTY;
12176#endif
12177        fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
12178        ext2fs_flush(fs);
12179        fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
12180}
12181#endif  /* ENABLE_SWAPFS */
12182
12183#endif
12184
12185/*
12186 * util.c --- miscellaneous utilities
12187 */
12188
12189
12190void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
12191                             const char *description)
12192{
12193        void *ret;
12194        char buf[256];
12195
12196        ret = xzalloc(size);
12197        return ret;
12198}
12199
12200static char *string_copy(const char *str, int len)
12201{
12202        char    *ret;
12203
12204        if (!str)
12205                return NULL;
12206        if (!len)
12207                len = strlen(str);
12208        ret = xmalloc(len+1);
12209        strncpy(ret, str, len);
12210        ret[len] = 0;
12211        return ret;
12212}
12213
12214#ifndef HAVE_CONIO_H
12215static int read_a_char(void)
12216{
12217        char    c;
12218        int     r;
12219        int     fail = 0;
12220
12221        while (1) {
12222                if (e2fsck_global_ctx &&
12223                    (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
12224                        return 3;
12225                }
12226                r = read(0, &c, 1);
12227                if (r == 1)
12228                        return c;
12229                if (fail++ > 100)
12230                        break;
12231        }
12232        return EOF;
12233}
12234#endif
12235
12236static int ask_yn(const char * string, int def)
12237{
12238        int             c;
12239        const char      *defstr;
12240        static const char short_yes[] = "yY";
12241        static const char short_no[] = "nN";
12242
12243#ifdef HAVE_TERMIOS_H
12244        struct termios  termios, tmp;
12245
12246        tcgetattr (0, &termios);
12247        tmp = termios;
12248        tmp.c_lflag &= ~(ICANON | ECHO);
12249        tmp.c_cc[VMIN] = 1;
12250        tmp.c_cc[VTIME] = 0;
12251        tcsetattr_stdin_TCSANOW(&tmp);
12252#endif
12253
12254        if (def == 1)
12255                defstr = "<y>";
12256        else if (def == 0)
12257                defstr = "<n>";
12258        else
12259                defstr = " (y/n)";
12260        printf("%s%s? ", string, defstr);
12261        while (1) {
12262                fflush (stdout);
12263                if ((c = read_a_char()) == EOF)
12264                        break;
12265                if (c == 3) {
12266#ifdef HAVE_TERMIOS_H
12267                        tcsetattr_stdin_TCSANOW(&termios);
12268#endif
12269                        if (e2fsck_global_ctx &&
12270                            e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) {
12271                                puts("\n");
12272                                longjmp(e2fsck_global_ctx->abort_loc, 1);
12273                        }
12274                        puts(_("cancelled!\n"));
12275                        return 0;
12276                }
12277                if (strchr(short_yes, (char) c)) {
12278                        def = 1;
12279                        break;
12280                }
12281                else if (strchr(short_no, (char) c)) {
12282                        def = 0;
12283                        break;
12284                }
12285                else if ((c == ' ' || c == '\n') && (def != -1))
12286                        break;
12287        }
12288        if (def)
12289                puts("yes\n");
12290        else
12291                puts ("no\n");
12292#ifdef HAVE_TERMIOS_H
12293        tcsetattr_stdin_TCSANOW(&termios);
12294#endif
12295        return def;
12296}
12297
12298int ask (e2fsck_t ctx, const char * string, int def)
12299{
12300        if (ctx->options & E2F_OPT_NO) {
12301                printf(_("%s? no\n\n"), string);
12302                return 0;
12303        }
12304        if (ctx->options & E2F_OPT_YES) {
12305                printf(_("%s? yes\n\n"), string);
12306                return 1;
12307        }
12308        if (ctx->options & E2F_OPT_PREEN) {
12309                printf("%s? %s\n\n", string, def ? _("yes") : _("no"));
12310                return def;
12311        }
12312        return ask_yn(string, def);
12313}
12314
12315void e2fsck_read_bitmaps(e2fsck_t ctx)
12316{
12317        ext2_filsys fs = ctx->fs;
12318        errcode_t       retval;
12319
12320        if (ctx->invalid_bitmaps) {
12321                bb_error_msg(_("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
12322                        ctx->device_name);
12323                bb_error_msg_and_die(0);
12324        }
12325
12326        ehandler_operation(_("reading inode and block bitmaps"));
12327        retval = ext2fs_read_bitmaps(fs);
12328        ehandler_operation(0);
12329        if (retval) {
12330                bb_error_msg(_("while retrying to read bitmaps for %s"),
12331                        ctx->device_name);
12332                bb_error_msg_and_die(0);
12333        }
12334}
12335
12336static void e2fsck_write_bitmaps(e2fsck_t ctx)
12337{
12338        ext2_filsys fs = ctx->fs;
12339        errcode_t       retval;
12340
12341        if (ext2fs_test_bb_dirty(fs)) {
12342                ehandler_operation(_("writing block bitmaps"));
12343                retval = ext2fs_write_block_bitmap(fs);
12344                ehandler_operation(0);
12345                if (retval) {
12346                        bb_error_msg(_("while retrying to write block bitmaps for %s"),
12347                                ctx->device_name);
12348                        bb_error_msg_and_die(0);
12349                }
12350        }
12351
12352        if (ext2fs_test_ib_dirty(fs)) {
12353                ehandler_operation(_("writing inode bitmaps"));
12354                retval = ext2fs_write_inode_bitmap(fs);
12355                ehandler_operation(0);
12356                if (retval) {
12357                        bb_error_msg(_("while retrying to write inode bitmaps for %s"),
12358                                ctx->device_name);
12359                        bb_error_msg_and_die(0);
12360                }
12361        }
12362}
12363
12364void preenhalt(e2fsck_t ctx)
12365{
12366        ext2_filsys fs = ctx->fs;
12367
12368        if (!(ctx->options & E2F_OPT_PREEN))
12369                return;
12370        fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
12371                "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
12372               ctx->device_name);
12373        if (fs != NULL) {
12374                fs->super->s_state |= EXT2_ERROR_FS;
12375                ext2fs_mark_super_dirty(fs);
12376                ext2fs_close(fs);
12377        }
12378        exit(EXIT_UNCORRECTED);
12379}
12380
12381void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
12382                              struct ext2_inode * inode, const char *proc)
12383{
12384        int retval;
12385
12386        retval = ext2fs_read_inode(ctx->fs, ino, inode);
12387        if (retval) {
12388                bb_error_msg(_("while reading inode %ld in %s"), ino, proc);
12389                bb_error_msg_and_die(0);
12390        }
12391}
12392
12393extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
12394                               struct ext2_inode * inode, int bufsize,
12395                               const char *proc)
12396{
12397        int retval;
12398
12399        retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
12400        if (retval) {
12401                bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12402                bb_error_msg_and_die(0);
12403        }
12404}
12405
12406extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
12407                               struct ext2_inode * inode, const char *proc)
12408{
12409        int retval;
12410
12411        retval = ext2fs_write_inode(ctx->fs, ino, inode);
12412        if (retval) {
12413                bb_error_msg(_("while writing inode %ld in %s"), ino, proc);
12414                bb_error_msg_and_die(0);
12415        }
12416}
12417
12418blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
12419                   io_manager manager)
12420{
12421        struct ext2_super_block *sb;
12422        io_channel              io = NULL;
12423        void                    *buf = NULL;
12424        int                     blocksize;
12425        blk_t                   superblock, ret_sb = 8193;
12426
12427        if (fs && fs->super) {
12428                ret_sb = (fs->super->s_blocks_per_group +
12429                          fs->super->s_first_data_block);
12430                if (ctx) {
12431                        ctx->superblock = ret_sb;
12432                        ctx->blocksize = fs->blocksize;
12433                }
12434                return ret_sb;
12435        }
12436
12437        if (ctx) {
12438                if (ctx->blocksize) {
12439                        ret_sb = ctx->blocksize * 8;
12440                        if (ctx->blocksize == 1024)
12441                                ret_sb++;
12442                        ctx->superblock = ret_sb;
12443                        return ret_sb;
12444                }
12445                ctx->superblock = ret_sb;
12446                ctx->blocksize = 1024;
12447        }
12448
12449        if (!name || !manager)
12450                goto cleanup;
12451
12452        if (manager->open(name, 0, &io) != 0)
12453                goto cleanup;
12454
12455        if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
12456                goto cleanup;
12457        sb = (struct ext2_super_block *) buf;
12458
12459        for (blocksize = EXT2_MIN_BLOCK_SIZE;
12460             blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
12461                superblock = blocksize*8;
12462                if (blocksize == 1024)
12463                        superblock++;
12464                io_channel_set_blksize(io, blocksize);
12465                if (io_channel_read_blk(io, superblock,
12466                                        -SUPERBLOCK_SIZE, buf))
12467                        continue;
12468#if BB_BIG_ENDIAN
12469                if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
12470                        ext2fs_swap_super(sb);
12471#endif
12472                if (sb->s_magic == EXT2_SUPER_MAGIC) {
12473                        ret_sb = superblock;
12474                        if (ctx) {
12475                                ctx->superblock = superblock;
12476                                ctx->blocksize = blocksize;
12477                        }
12478                        break;
12479                }
12480        }
12481
12482cleanup:
12483        if (io)
12484                io_channel_close(io);
12485        ext2fs_free_mem(&buf);
12486        return ret_sb;
12487}
12488
12489
12490/*
12491 * This function runs through the e2fsck passes and calls them all,
12492 * returning restart, abort, or cancel as necessary...
12493 */
12494typedef void (*pass_t)(e2fsck_t ctx);
12495
12496static const pass_t e2fsck_passes[] = {
12497        e2fsck_pass1, e2fsck_pass2, e2fsck_pass3, e2fsck_pass4,
12498        e2fsck_pass5, 0 };
12499
12500#define E2F_FLAG_RUN_RETURN     (E2F_FLAG_SIGNAL_MASK|E2F_FLAG_RESTART)
12501
12502static int e2fsck_run(e2fsck_t ctx)
12503{
12504        int     i;
12505        pass_t  e2fsck_pass;
12506
12507        if (setjmp(ctx->abort_loc)) {
12508                ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12509                return (ctx->flags & E2F_FLAG_RUN_RETURN);
12510        }
12511        ctx->flags |= E2F_FLAG_SETJMP_OK;
12512
12513        for (i=0; (e2fsck_pass = e2fsck_passes[i]); i++) {
12514                if (ctx->flags & E2F_FLAG_RUN_RETURN)
12515                        break;
12516                e2fsck_pass(ctx);
12517                if (ctx->progress)
12518                        (void) (ctx->progress)(ctx, 0, 0, 0);
12519        }
12520        ctx->flags &= ~E2F_FLAG_SETJMP_OK;
12521
12522        if (ctx->flags & E2F_FLAG_RUN_RETURN)
12523                return (ctx->flags & E2F_FLAG_RUN_RETURN);
12524        return 0;
12525}
12526
12527
12528/*
12529 * unix.c - The unix-specific code for e2fsck
12530 */
12531
12532
12533/* Command line options */
12534static int swapfs;
12535#ifdef ENABLE_SWAPFS
12536static int normalize_swapfs;
12537#endif
12538static int cflag;               /* check disk */
12539static int show_version_only;
12540static int verbose;
12541
12542#define P_E2(singular, plural, n)       n, ((n) == 1 ? singular : plural)
12543
12544static void show_stats(e2fsck_t ctx)
12545{
12546        ext2_filsys fs = ctx->fs;
12547        int inodes, inodes_used, blocks, blocks_used;
12548        int dir_links;
12549        int num_files, num_links;
12550        int frag_percent;
12551
12552        dir_links = 2 * ctx->fs_directory_count - 1;
12553        num_files = ctx->fs_total_count - dir_links;
12554        num_links = ctx->fs_links_count - dir_links;
12555        inodes = fs->super->s_inodes_count;
12556        inodes_used = (fs->super->s_inodes_count -
12557                       fs->super->s_free_inodes_count);
12558        blocks = fs->super->s_blocks_count;
12559        blocks_used = (fs->super->s_blocks_count -
12560                       fs->super->s_free_blocks_count);
12561
12562        frag_percent = (10000 * ctx->fs_fragmented) / inodes_used;
12563        frag_percent = (frag_percent + 5) / 10;
12564
12565        if (!verbose) {
12566                printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
12567                       ctx->device_name, inodes_used, inodes,
12568                       frag_percent / 10, frag_percent % 10,
12569                       blocks_used, blocks);
12570                return;
12571        }
12572        printf("\n%8d inode%s used (%d%%)\n", P_E2("", "s", inodes_used),
12573                100 * inodes_used / inodes);
12574        printf("%8d non-contiguous inode%s (%0d.%d%%)\n",
12575                P_E2("", "s", ctx->fs_fragmented),
12576                frag_percent / 10, frag_percent % 10);
12577        printf(_("         # of inodes with ind/dind/tind blocks: %d/%d/%d\n"),
12578                ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
12579        printf("%8d block%s used (%d%%)\n", P_E2("", "s", blocks_used),
12580                (int) ((long long) 100 * blocks_used / blocks));
12581        printf("%8d large file%s\n", P_E2("", "s", ctx->large_files));
12582        printf("\n%8d regular file%s\n", P_E2("", "s", ctx->fs_regular_count));
12583        printf("%8d director%s\n", P_E2("y", "ies", ctx->fs_directory_count));
12584        printf("%8d character device file%s\n", P_E2("", "s", ctx->fs_chardev_count));
12585        printf("%8d block device file%s\n", P_E2("", "s", ctx->fs_blockdev_count));
12586        printf("%8d fifo%s\n", P_E2("", "s", ctx->fs_fifo_count));
12587        printf("%8d link%s\n", P_E2("", "s", ctx->fs_links_count - dir_links));
12588        printf("%8d symbolic link%s", P_E2("", "s", ctx->fs_symlinks_count));
12589        printf(" (%d fast symbolic link%s)\n", P_E2("", "s", ctx->fs_fast_symlinks_count));
12590        printf("%8d socket%s--------\n\n", P_E2("", "s", ctx->fs_sockets_count));
12591        printf("%8d file%s\n", P_E2("", "s", ctx->fs_total_count - dir_links));
12592}
12593
12594static void check_mount(e2fsck_t ctx)
12595{
12596        errcode_t       retval;
12597        int             cont;
12598
12599        retval = ext2fs_check_if_mounted(ctx->filesystem_name,
12600                                         &ctx->mount_flags);
12601        if (retval) {
12602                bb_error_msg(_("while determining whether %s is mounted"),
12603                        ctx->filesystem_name);
12604                return;
12605        }
12606
12607        /*
12608         * If the filesystem isn't mounted, or it's the root filesystem
12609         * and it's mounted read-only, then everything's fine.
12610         */
12611        if ((!(ctx->mount_flags & EXT2_MF_MOUNTED)) ||
12612            ((ctx->mount_flags & EXT2_MF_ISROOT) &&
12613             (ctx->mount_flags & EXT2_MF_READONLY)))
12614                return;
12615
12616        if (ctx->options & E2F_OPT_READONLY) {
12617                printf(_("Warning!  %s is mounted.\n"), ctx->filesystem_name);
12618                return;
12619        }
12620
12621        printf(_("%s is mounted.  "), ctx->filesystem_name);
12622        if (!ctx->interactive)
12623                bb_error_msg_and_die(_("can't continue, aborting"));
12624        printf(_("\n\n\007\007\007\007WARNING!!!  "
12625               "Running e2fsck on a mounted filesystem may cause\n"
12626               "SEVERE filesystem damage.\007\007\007\n\n"));
12627        cont = ask_yn(_("Do you really want to continue"), -1);
12628        if (!cont) {
12629                printf(_("check aborted.\n"));
12630                exit(0);
12631        }
12632}
12633
12634static int is_on_batt(void)
12635{
12636        FILE    *f;
12637        DIR     *d;
12638        char    tmp[80], tmp2[80], fname[80];
12639        unsigned int    acflag;
12640        struct dirent*  de;
12641
12642        f = fopen_for_read("/proc/apm");
12643        if (f) {
12644                if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
12645                        acflag = 1;
12646                fclose(f);
12647                return (acflag != 1);
12648        }
12649        d = opendir("/proc/acpi/ac_adapter");
12650        if (d) {
12651                while ((de=readdir(d)) != NULL) {
12652                        if (!strncmp(".", de->d_name, 1))
12653                                continue;
12654                        snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
12655                                 de->d_name);
12656                        f = fopen_for_read(fname);
12657                        if (!f)
12658                                continue;
12659                        if (fscanf(f, "%s %s", tmp2, tmp) != 2)
12660                                tmp[0] = 0;
12661                        fclose(f);
12662                        if (strncmp(tmp, "off-line", 8) == 0) {
12663                                closedir(d);
12664                                return 1;
12665                        }
12666                }
12667                closedir(d);
12668        }
12669        return 0;
12670}
12671
12672/*
12673 * This routine checks to see if a filesystem can be skipped; if so,
12674 * it will exit with EXIT_OK.  Under some conditions it will print a
12675 * message explaining why a check is being forced.
12676 */
12677static void check_if_skip(e2fsck_t ctx)
12678{
12679        ext2_filsys fs = ctx->fs;
12680        const char *reason = NULL;
12681        unsigned int reason_arg = 0;
12682        long next_check;
12683        int batt = is_on_batt();
12684        time_t now = time(NULL);
12685
12686        if ((ctx->options & E2F_OPT_FORCE) || cflag || swapfs)
12687                return;
12688
12689        if ((fs->super->s_state & EXT2_ERROR_FS) ||
12690            !ext2fs_test_valid(fs))
12691                reason = _(" contains a file system with errors");
12692        else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
12693                reason = _(" was not cleanly unmounted");
12694        else if ((fs->super->s_max_mnt_count > 0) &&
12695                 (fs->super->s_mnt_count >=
12696                  (unsigned) fs->super->s_max_mnt_count)) {
12697                reason = _(" has been mounted %u times without being checked");
12698                reason_arg = fs->super->s_mnt_count;
12699                if (batt && (fs->super->s_mnt_count <
12700                             (unsigned) fs->super->s_max_mnt_count*2))
12701                        reason = 0;
12702        } else if (fs->super->s_checkinterval &&
12703                   ((now - fs->super->s_lastcheck) >=
12704                    fs->super->s_checkinterval)) {
12705                reason = _(" has gone %u days without being checked");
12706                reason_arg = (now - fs->super->s_lastcheck)/(3600*24);
12707                if (batt && ((now - fs->super->s_lastcheck) <
12708                             fs->super->s_checkinterval*2))
12709                        reason = 0;
12710        }
12711        if (reason) {
12712                fputs(ctx->device_name, stdout);
12713                printf(reason, reason_arg);
12714                fputs(_(", check forced.\n"), stdout);
12715                return;
12716        }
12717        printf(_("%s: clean, %d/%d files, %d/%d blocks"), ctx->device_name,
12718               fs->super->s_inodes_count - fs->super->s_free_inodes_count,
12719               fs->super->s_inodes_count,
12720               fs->super->s_blocks_count - fs->super->s_free_blocks_count,
12721               fs->super->s_blocks_count);
12722        next_check = 100000;
12723        if (fs->super->s_max_mnt_count > 0) {
12724                next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
12725                if (next_check <= 0)
12726                        next_check = 1;
12727        }
12728        if (fs->super->s_checkinterval &&
12729            ((now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
12730                next_check = 1;
12731        if (next_check <= 5) {
12732                if (next_check == 1)
12733                        fputs(_(" (check after next mount)"), stdout);
12734                else
12735                        printf(_(" (check in %ld mounts)"), next_check);
12736        }
12737        bb_putchar('\n');
12738        ext2fs_close(fs);
12739        ctx->fs = NULL;
12740        e2fsck_free_context(ctx);
12741        exit(EXIT_OK);
12742}
12743
12744/*
12745 * For completion notice
12746 */
12747struct percent_tbl {
12748        int     max_pass;
12749        int     table[32];
12750};
12751static const struct percent_tbl e2fsck_tbl = {
12752        5, { 0, 70, 90, 92,  95, 100 }
12753};
12754
12755static char bar[128], spaces[128];
12756
12757static float calc_percent(const struct percent_tbl *tbl, int pass, int curr,
12758                          int max)
12759{
12760        float   percent;
12761
12762        if (pass <= 0)
12763                return 0.0;
12764        if (pass > tbl->max_pass || max == 0)
12765                return 100.0;
12766        percent = ((float) curr) / ((float) max);
12767        return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
12768                + tbl->table[pass-1]);
12769}
12770
12771void e2fsck_clear_progbar(e2fsck_t ctx)
12772{
12773        if (!(ctx->flags & E2F_FLAG_PROG_BAR))
12774                return;
12775
12776        printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
12777               ctx->stop_meta);
12778        fflush(stdout);
12779        ctx->flags &= ~E2F_FLAG_PROG_BAR;
12780}
12781
12782int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
12783                           unsigned int dpynum)
12784{
12785        static const char spinner[] = "\\|/-";
12786        int     i;
12787        unsigned int    tick;
12788        struct timeval  tv;
12789        int dpywidth;
12790        int fixed_percent;
12791
12792        if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
12793                return 0;
12794
12795        /*
12796         * Calculate the new progress position.  If the
12797         * percentage hasn't changed, then we skip out right
12798         * away.
12799         */
12800        fixed_percent = (int) ((10 * percent) + 0.5);
12801        if (ctx->progress_last_percent == fixed_percent)
12802                return 0;
12803        ctx->progress_last_percent = fixed_percent;
12804
12805        /*
12806         * If we've already updated the spinner once within
12807         * the last 1/8th of a second, no point doing it
12808         * again.
12809         */
12810        gettimeofday(&tv, NULL);
12811        tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
12812        if ((tick == ctx->progress_last_time) &&
12813            (fixed_percent != 0) && (fixed_percent != 1000))
12814                return 0;
12815        ctx->progress_last_time = tick;
12816
12817        /*
12818         * Advance the spinner, and note that the progress bar
12819         * will be on the screen
12820         */
12821        ctx->progress_pos = (ctx->progress_pos+1) & 3;
12822        ctx->flags |= E2F_FLAG_PROG_BAR;
12823
12824        dpywidth = 66 - strlen(label);
12825        dpywidth = 8 * (dpywidth / 8);
12826        if (dpynum)
12827                dpywidth -= 8;
12828
12829        i = ((percent * dpywidth) + 50) / 100;
12830        printf("%s%s: |%s%s", ctx->start_meta, label,
12831               bar + (sizeof(bar) - (i+1)),
12832               spaces + (sizeof(spaces) - (dpywidth - i + 1)));
12833        if (fixed_percent == 1000)
12834                bb_putchar('|');
12835        else
12836                bb_putchar(spinner[ctx->progress_pos & 3]);
12837        printf(" %4.1f%%  ", percent);
12838        if (dpynum)
12839                printf("%u\r", dpynum);
12840        else
12841                fputs(" \r", stdout);
12842        fputs(ctx->stop_meta, stdout);
12843
12844        if (fixed_percent == 1000)
12845                e2fsck_clear_progbar(ctx);
12846        fflush(stdout);
12847
12848        return 0;
12849}
12850
12851static int e2fsck_update_progress(e2fsck_t ctx, int pass,
12852                                  unsigned long cur, unsigned long max)
12853{
12854        char buf[80];
12855        float percent;
12856
12857        if (pass == 0)
12858                return 0;
12859
12860        if (ctx->progress_fd) {
12861                sprintf(buf, "%d %lu %lu\n", pass, cur, max);
12862                xwrite_str(ctx->progress_fd, buf);
12863        } else {
12864                percent = calc_percent(&e2fsck_tbl, pass, cur, max);
12865                e2fsck_simple_progress(ctx, ctx->device_name,
12866                                       percent, 0);
12867        }
12868        return 0;
12869}
12870
12871static void reserve_stdio_fds(void)
12872{
12873        int     fd;
12874
12875        while (1) {
12876                fd = open(bb_dev_null, O_RDWR);
12877                if (fd > 2)
12878                        break;
12879                if (fd < 0) {
12880                        fprintf(stderr, _("ERROR: Cannot open "
12881                                "/dev/null (%s)\n"),
12882                                strerror(errno));
12883                        break;
12884                }
12885        }
12886        close(fd);
12887}
12888
12889static void signal_progress_on(int sig FSCK_ATTR((unused)))
12890{
12891        e2fsck_t ctx = e2fsck_global_ctx;
12892
12893        if (!ctx)
12894                return;
12895
12896        ctx->progress = e2fsck_update_progress;
12897        ctx->progress_fd = 0;
12898}
12899
12900static void signal_progress_off(int sig FSCK_ATTR((unused)))
12901{
12902        e2fsck_t ctx = e2fsck_global_ctx;
12903
12904        if (!ctx)
12905                return;
12906
12907        e2fsck_clear_progbar(ctx);
12908        ctx->progress = 0;
12909}
12910
12911static void signal_cancel(int sig FSCK_ATTR((unused)))
12912{
12913        e2fsck_t ctx = e2fsck_global_ctx;
12914
12915        if (!ctx)
12916                exit(FSCK_CANCELED);
12917
12918        ctx->flags |= E2F_FLAG_CANCEL;
12919}
12920
12921static void parse_extended_opts(e2fsck_t ctx, const char *opts)
12922{
12923        char    *buf, *token, *next, *p, *arg;
12924        int     ea_ver;
12925        int     extended_usage = 0;
12926
12927        buf = string_copy(opts, 0);
12928        for (token = buf; token && *token; token = next) {
12929                p = strchr(token, ',');
12930                next = 0;
12931                if (p) {
12932                        *p = 0;
12933                        next = p+1;
12934                }
12935                arg = strchr(token, '=');
12936                if (arg) {
12937                        *arg = 0;
12938                        arg++;
12939                }
12940                if (strcmp(token, "ea_ver") == 0) {
12941                        if (!arg) {
12942                                extended_usage++;
12943                                continue;
12944                        }
12945                        ea_ver = strtoul(arg, &p, 0);
12946                        if (*p ||
12947                            ((ea_ver != 1) && (ea_ver != 2))) {
12948                                fprintf(stderr,
12949                                        _("Invalid EA version.\n"));
12950                                extended_usage++;
12951                                continue;
12952                        }
12953                        ctx->ext_attr_ver = ea_ver;
12954                } else {
12955                        fprintf(stderr, _("Unknown extended option: %s\n"),
12956                                token);
12957                        extended_usage++;
12958                }
12959        }
12960        if (extended_usage) {
12961                bb_error_msg_and_die(
12962                        "Extended options are separated by commas, "
12963                        "and may take an argument which\n"
12964                        "is set off by an equals ('=') sign.  "
12965                        "Valid extended options are:\n"
12966                        "\tea_ver=<ea_version (1 or 2)>\n\n");
12967        }
12968}
12969
12970
12971static errcode_t PRS(int argc, char **argv, e2fsck_t *ret_ctx)
12972{
12973        int             flush = 0;
12974        int             c, fd;
12975        e2fsck_t        ctx;
12976        errcode_t       retval;
12977        struct sigaction        sa;
12978        char            *extended_opts = 0;
12979
12980        retval = e2fsck_allocate_context(&ctx);
12981        if (retval)
12982                return retval;
12983
12984        *ret_ctx = ctx;
12985
12986        setvbuf(stdout, NULL, _IONBF, BUFSIZ);
12987        setvbuf(stderr, NULL, _IONBF, BUFSIZ);
12988        if (isatty(0) && isatty(1)) {
12989                ctx->interactive = 1;
12990        } else {
12991                ctx->start_meta[0] = '\001';
12992                ctx->stop_meta[0] = '\002';
12993        }
12994        memset(bar, '=', sizeof(bar)-1);
12995        memset(spaces, ' ', sizeof(spaces)-1);
12996        blkid_get_cache(&ctx->blkid, NULL);
12997
12998        if (argc && *argv)
12999                ctx->program_name = *argv;
13000        else
13001                ctx->program_name = "e2fsck";
13002        while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
13003                switch (c) {
13004                case 'C':
13005                        ctx->progress = e2fsck_update_progress;
13006                        ctx->progress_fd = atoi(optarg);
13007                        if (!ctx->progress_fd)
13008                                break;
13009                        /* Validate the file descriptor to avoid disasters */
13010                        fd = dup(ctx->progress_fd);
13011                        if (fd < 0) {
13012                                fprintf(stderr,
13013                                _("Error validating file descriptor %d: %s\n"),
13014                                        ctx->progress_fd,
13015                                        error_message(errno));
13016                                bb_error_msg_and_die(_("Invalid completion information file descriptor"));
13017                        } else
13018                                close(fd);
13019                        break;
13020                case 'D':
13021                        ctx->options |= E2F_OPT_COMPRESS_DIRS;
13022                        break;
13023                case 'E':
13024                        extended_opts = optarg;
13025                        break;
13026                case 'p':
13027                case 'a':
13028                        if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
13029                        conflict_opt:
13030                                bb_error_msg_and_die(_("only one the options -p/-a, -n or -y may be specified"));
13031                        }
13032                        ctx->options |= E2F_OPT_PREEN;
13033                        break;
13034                case 'n':
13035                        if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
13036                                goto conflict_opt;
13037                        ctx->options |= E2F_OPT_NO;
13038                        break;
13039                case 'y':
13040                        if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
13041                                goto conflict_opt;
13042                        ctx->options |= E2F_OPT_YES;
13043                        break;
13044                case 't':
13045                        /* FIXME - This needs to go away in a future path - will change binary */
13046                        fprintf(stderr, _("The -t option is not "
13047                                "supported on this version of e2fsck.\n"));
13048                        break;
13049                case 'c':
13050                        if (cflag++)
13051                                ctx->options |= E2F_OPT_WRITECHECK;
13052                        ctx->options |= E2F_OPT_CHECKBLOCKS;
13053                        break;
13054                case 'r':
13055                        /* What we do by default, anyway! */
13056                        break;
13057                case 'b':
13058                        ctx->use_superblock = atoi(optarg);
13059                        ctx->flags |= E2F_FLAG_SB_SPECIFIED;
13060                        break;
13061                case 'B':
13062                        ctx->blocksize = atoi(optarg);
13063                        break;
13064                case 'I':
13065                        ctx->inode_buffer_blocks = atoi(optarg);
13066                        break;
13067                case 'j':
13068                        ctx->journal_name = string_copy(optarg, 0);
13069                        break;
13070                case 'P':
13071                        ctx->process_inode_size = atoi(optarg);
13072                        break;
13073                case 'd':
13074                        ctx->options |= E2F_OPT_DEBUG;
13075                        break;
13076                case 'f':
13077                        ctx->options |= E2F_OPT_FORCE;
13078                        break;
13079                case 'F':
13080                        flush = 1;
13081                        break;
13082                case 'v':
13083                        verbose = 1;
13084                        break;
13085                case 'V':
13086                        show_version_only = 1;
13087                        break;
13088                case 'N':
13089                        ctx->device_name = optarg;
13090                        break;
13091#ifdef ENABLE_SWAPFS
13092                case 's':
13093                        normalize_swapfs = 1;
13094                case 'S':
13095                        swapfs = 1;
13096                        break;
13097#else
13098                case 's':
13099                case 'S':
13100                        fprintf(stderr, _("Byte-swapping filesystems "
13101                                          "not compiled in this version "
13102                                          "of e2fsck\n"));
13103                        exit(1);
13104#endif
13105                default:
13106                        bb_show_usage();
13107                }
13108        if (show_version_only)
13109                return 0;
13110        if (optind != argc - 1)
13111                bb_show_usage();
13112        if ((ctx->options & E2F_OPT_NO) &&
13113            !cflag && !swapfs && !(ctx->options & E2F_OPT_COMPRESS_DIRS))
13114                ctx->options |= E2F_OPT_READONLY;
13115        ctx->io_options = strchr(argv[optind], '?');
13116        if (ctx->io_options)
13117                *ctx->io_options++ = 0;
13118        ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
13119        if (!ctx->filesystem_name) {
13120                bb_error_msg(_("Unable to resolve '%s'"), argv[optind]);
13121                bb_error_msg_and_die(0);
13122        }
13123        if (extended_opts)
13124                parse_extended_opts(ctx, extended_opts);
13125
13126        if (flush) {
13127                fd = open(ctx->filesystem_name, O_RDONLY, 0);
13128                if (fd < 0) {
13129                        bb_error_msg(_("while opening %s for flushing"),
13130                                ctx->filesystem_name);
13131                        bb_error_msg_and_die(0);
13132                }
13133                if ((retval = ext2fs_sync_device(fd, 1))) {
13134                        bb_error_msg(_("while trying to flush %s"),
13135                                ctx->filesystem_name);
13136                        bb_error_msg_and_die(0);
13137                }
13138                close(fd);
13139        }
13140#ifdef ENABLE_SWAPFS
13141        if (swapfs && cflag) {
13142                        fprintf(stderr, _("Incompatible options not "
13143                                          "allowed when byte-swapping.\n"));
13144                        exit(EXIT_USAGE);
13145        }
13146#endif
13147        /*
13148         * Set up signal action
13149         */
13150        memset(&sa, 0, sizeof(struct sigaction));
13151        sa.sa_handler = signal_cancel;
13152        sigaction(SIGINT, &sa, 0);
13153        sigaction(SIGTERM, &sa, 0);
13154#ifdef SA_RESTART
13155        sa.sa_flags = SA_RESTART;
13156#endif
13157        e2fsck_global_ctx = ctx;
13158        sa.sa_handler = signal_progress_on;
13159        sigaction(SIGUSR1, &sa, 0);
13160        sa.sa_handler = signal_progress_off;
13161        sigaction(SIGUSR2, &sa, 0);
13162
13163        /* Update our PATH to include /sbin if we need to run badblocks  */
13164        if (cflag)
13165                e2fs_set_sbin_path();
13166        return 0;
13167}
13168
13169static const char my_ver_string[] = E2FSPROGS_VERSION;
13170static const char my_ver_date[] = E2FSPROGS_DATE;
13171
13172int e2fsck_main (int argc, char **argv);
13173int e2fsck_main (int argc, char **argv)
13174{
13175        errcode_t       retval;
13176        int             exit_value = EXIT_OK;
13177        ext2_filsys     fs = 0;
13178        io_manager      io_ptr;
13179        struct ext2_super_block *sb;
13180        const char      *lib_ver_date;
13181        int             my_ver, lib_ver;
13182        e2fsck_t        ctx;
13183        struct problem_context pctx;
13184        int flags, run_result;
13185
13186        clear_problem_context(&pctx);
13187
13188        my_ver = ext2fs_parse_version_string(my_ver_string);
13189        lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
13190        if (my_ver > lib_ver) {
13191                fprintf( stderr, _("Error: ext2fs library version "
13192                        "out of date!\n"));
13193                show_version_only++;
13194        }
13195
13196        retval = PRS(argc, argv, &ctx);
13197        if (retval) {
13198                bb_error_msg(_("while trying to initialize program"));
13199                exit(EXIT_ERROR);
13200        }
13201        reserve_stdio_fds();
13202
13203        if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
13204                fprintf(stderr, "e2fsck %s (%s)\n", my_ver_string,
13205                         my_ver_date);
13206
13207        if (show_version_only) {
13208                fprintf(stderr, _("\tUsing %s, %s\n"),
13209                        error_message(EXT2_ET_BASE), lib_ver_date);
13210                exit(EXIT_OK);
13211        }
13212
13213        check_mount(ctx);
13214
13215        if (!(ctx->options & E2F_OPT_PREEN) &&
13216            !(ctx->options & E2F_OPT_NO) &&
13217            !(ctx->options & E2F_OPT_YES)) {
13218                if (!ctx->interactive)
13219                        bb_error_msg_and_die(_("need terminal for interactive repairs"));
13220        }
13221        ctx->superblock = ctx->use_superblock;
13222restart:
13223#ifdef CONFIG_TESTIO_DEBUG
13224        io_ptr = test_io_manager;
13225        test_io_backing_manager = unix_io_manager;
13226#else
13227        io_ptr = unix_io_manager;
13228#endif
13229        flags = 0;
13230        if ((ctx->options & E2F_OPT_READONLY) == 0)
13231                flags |= EXT2_FLAG_RW;
13232
13233        if (ctx->superblock && ctx->blocksize) {
13234                retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13235                                      flags, ctx->superblock, ctx->blocksize,
13236                                      io_ptr, &fs);
13237        } else if (ctx->superblock) {
13238                int blocksize;
13239                for (blocksize = EXT2_MIN_BLOCK_SIZE;
13240                     blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
13241                        retval = ext2fs_open2(ctx->filesystem_name,
13242                                              ctx->io_options, flags,
13243                                              ctx->superblock, blocksize,
13244                                              io_ptr, &fs);
13245                        if (!retval)
13246                                break;
13247                }
13248        } else
13249                retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
13250                                      flags, 0, 0, io_ptr, &fs);
13251        if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
13252            !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
13253            ((retval == EXT2_ET_BAD_MAGIC) ||
13254             ((retval == 0) && ext2fs_check_desc(fs)))) {
13255                if (!fs || (fs->group_desc_count > 1)) {
13256                        printf(_("%s trying backup blocks...\n"),
13257                               retval ? _("Couldn't find ext2 superblock,") :
13258                               _("Group descriptors look bad..."));
13259                        get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
13260                        if (fs)
13261                                ext2fs_close(fs);
13262                        goto restart;
13263                }
13264        }
13265        if (retval) {
13266                bb_error_msg(_("while trying to open %s"),
13267                        ctx->filesystem_name);
13268                if (retval == EXT2_ET_REV_TOO_HIGH) {
13269                        printf(_("The filesystem revision is apparently "
13270                               "too high for this version of e2fsck.\n"
13271                               "(Or the filesystem superblock "
13272                               "is corrupt)\n\n"));
13273                        fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13274                } else if (retval == EXT2_ET_SHORT_READ)
13275                        printf(_("Could this be a zero-length partition?\n"));
13276                else if ((retval == EPERM) || (retval == EACCES))
13277                        printf(_("You must have %s access to the "
13278                               "filesystem or be root\n"),
13279                               (ctx->options & E2F_OPT_READONLY) ?
13280                               "r/o" : "r/w");
13281                else if (retval == ENXIO)
13282                        printf(_("Possibly non-existent or swap device?\n"));
13283#ifdef EROFS
13284                else if (retval == EROFS)
13285                        printf(_("Disk write-protected; use the -n option "
13286                               "to do a read-only\n"
13287                               "check of the device.\n"));
13288#endif
13289                else
13290                        fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
13291                bb_error_msg_and_die(0);
13292        }
13293        ctx->fs = fs;
13294        fs->priv_data = ctx;
13295        sb = fs->super;
13296        if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
13297                bb_error_msg(_("while trying to open %s"),
13298                        ctx->filesystem_name);
13299        get_newer:
13300                bb_error_msg_and_die(_("Get a newer version of e2fsck!"));
13301        }
13302
13303        /*
13304         * Set the device name, which is used whenever we print error
13305         * or informational messages to the user.
13306         */
13307        if (ctx->device_name == 0 &&
13308            (sb->s_volume_name[0] != 0)) {
13309                ctx->device_name = string_copy(sb->s_volume_name,
13310                                               sizeof(sb->s_volume_name));
13311        }
13312        if (ctx->device_name == 0)
13313                ctx->device_name = ctx->filesystem_name;
13314
13315        /*
13316         * Make sure the ext3 superblock fields are consistent.
13317         */
13318        retval = e2fsck_check_ext3_journal(ctx);
13319        if (retval) {
13320                bb_error_msg(_("while checking ext3 journal for %s"),
13321                        ctx->device_name);
13322                bb_error_msg_and_die(0);
13323        }
13324
13325        /*
13326         * Check to see if we need to do ext3-style recovery.  If so,
13327         * do it, and then restart the fsck.
13328         */
13329        if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
13330                if (ctx->options & E2F_OPT_READONLY) {
13331                        printf(_("Warning: skipping journal recovery "
13332                                 "because doing a read-only filesystem "
13333                                 "check.\n"));
13334                        io_channel_flush(ctx->fs->io);
13335                } else {
13336                        if (ctx->flags & E2F_FLAG_RESTARTED) {
13337                                /*
13338                                 * Whoops, we attempted to run the
13339                                 * journal twice.  This should never
13340                                 * happen, unless the hardware or
13341                                 * device driver is being bogus.
13342                                 */
13343                                bb_error_msg(_("can't set superblock flags on %s"), ctx->device_name);
13344                                bb_error_msg_and_die(0);
13345                        }
13346                        retval = e2fsck_run_ext3_journal(ctx);
13347                        if (retval) {
13348                                bb_error_msg(_("while recovering ext3 journal of %s"),
13349                                        ctx->device_name);
13350                                bb_error_msg_and_die(0);
13351                        }
13352                        ext2fs_close(ctx->fs);
13353                        ctx->fs = 0;
13354                        ctx->flags |= E2F_FLAG_RESTARTED;
13355                        goto restart;
13356                }
13357        }
13358
13359        /*
13360         * Check for compatibility with the feature sets.  We need to
13361         * be more stringent than ext2fs_open().
13362         */
13363        if ((sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP) ||
13364            (sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP)) {
13365                bb_error_msg("(%s)", ctx->device_name);
13366                goto get_newer;
13367        }
13368        if (sb->s_feature_ro_compat & ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP) {
13369                bb_error_msg("(%s)", ctx->device_name);
13370                goto get_newer;
13371        }
13372#ifdef ENABLE_COMPRESSION
13373        /* FIXME - do we support this at all? */
13374        if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
13375                bb_error_msg(_("warning: compression support is experimental"));
13376#endif
13377#ifndef ENABLE_HTREE
13378        if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
13379                bb_error_msg(_("E2fsck not compiled with HTREE support,\n\t"
13380                          "but filesystem %s has HTREE directories."),
13381                        ctx->device_name);
13382                goto get_newer;
13383        }
13384#endif
13385
13386        /*
13387         * If the user specified a specific superblock, presumably the
13388         * master superblock has been trashed.  So we mark the
13389         * superblock as dirty, so it can be written out.
13390         */
13391        if (ctx->superblock &&
13392            !(ctx->options & E2F_OPT_READONLY))
13393                ext2fs_mark_super_dirty(fs);
13394
13395        /*
13396         * We only update the master superblock because (a) paranoia;
13397         * we don't want to corrupt the backup superblocks, and (b) we
13398         * don't need to update the mount count and last checked
13399         * fields in the backup superblock (the kernel doesn't
13400         * update the backup superblocks anyway).
13401         */
13402        fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
13403
13404        ehandler_init(fs->io);
13405
13406        if (ctx->superblock)
13407                set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
13408        ext2fs_mark_valid(fs);
13409        check_super_block(ctx);
13410        if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13411                bb_error_msg_and_die(0);
13412        check_if_skip(ctx);
13413        if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13414                bb_error_msg_and_die(0);
13415#ifdef ENABLE_SWAPFS
13416
13417#ifdef WORDS_BIGENDIAN
13418#define NATIVE_FLAG EXT2_FLAG_SWAP_BYTES
13419#else
13420#define NATIVE_FLAG 0
13421#endif
13422
13423
13424        if (normalize_swapfs) {
13425                if ((fs->flags & EXT2_FLAG_SWAP_BYTES) == NATIVE_FLAG) {
13426                        fprintf(stderr, _("%s: Filesystem byte order "
13427                                "already normalized.\n"), ctx->device_name);
13428                        bb_error_msg_and_die(0);
13429                }
13430        }
13431        if (swapfs) {
13432                swap_filesys(ctx);
13433                if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
13434                        bb_error_msg_and_die(0);
13435        }
13436#endif
13437
13438        /*
13439         * Mark the system as valid, 'til proven otherwise
13440         */
13441        ext2fs_mark_valid(fs);
13442
13443        retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
13444        if (retval) {
13445                bb_error_msg(_("while reading bad blocks inode"));
13446                preenhalt(ctx);
13447                printf(_("This doesn't bode well,"
13448                         " but we'll try to go on...\n"));
13449        }
13450
13451        run_result = e2fsck_run(ctx);
13452        e2fsck_clear_progbar(ctx);
13453        if (run_result == E2F_FLAG_RESTART) {
13454                printf(_("Restarting e2fsck from the beginning...\n"));
13455                retval = e2fsck_reset_context(ctx);
13456                if (retval) {
13457                        bb_error_msg(_("while resetting context"));
13458                        bb_error_msg_and_die(0);
13459                }
13460                ext2fs_close(fs);
13461                goto restart;
13462        }
13463        if (run_result & E2F_FLAG_CANCEL) {
13464                printf(_("%s: e2fsck canceled.\n"), ctx->device_name ?
13465                       ctx->device_name : ctx->filesystem_name);
13466                exit_value |= FSCK_CANCELED;
13467        }
13468        if (run_result & E2F_FLAG_ABORT)
13469                bb_error_msg_and_die(_("aborted"));
13470
13471        /* Cleanup */
13472        if (ext2fs_test_changed(fs)) {
13473                exit_value |= EXIT_NONDESTRUCT;
13474                if (!(ctx->options & E2F_OPT_PREEN))
13475                    printf(_("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
13476                               ctx->device_name);
13477                if (ctx->mount_flags & EXT2_MF_ISROOT) {
13478                        printf(_("%s: ***** REBOOT LINUX *****\n"),
13479                               ctx->device_name);
13480                        exit_value |= EXIT_DESTRUCT;
13481                }
13482        }
13483        if (!ext2fs_test_valid(fs)) {
13484                printf(_("\n%s: ********** WARNING: Filesystem still has "
13485                         "errors **********\n\n"), ctx->device_name);
13486                exit_value |= EXIT_UNCORRECTED;
13487                exit_value &= ~EXIT_NONDESTRUCT;
13488        }
13489        if (exit_value & FSCK_CANCELED)
13490                exit_value &= ~EXIT_NONDESTRUCT;
13491        else {
13492                show_stats(ctx);
13493                if (!(ctx->options & E2F_OPT_READONLY)) {
13494                        if (ext2fs_test_valid(fs)) {
13495                                if (!(sb->s_state & EXT2_VALID_FS))
13496                                        exit_value |= EXIT_NONDESTRUCT;
13497                                sb->s_state = EXT2_VALID_FS;
13498                        } else
13499                                sb->s_state &= ~EXT2_VALID_FS;
13500                        sb->s_mnt_count = 0;
13501                        sb->s_lastcheck = time(NULL);
13502                        ext2fs_mark_super_dirty(fs);
13503                }
13504        }
13505
13506        e2fsck_write_bitmaps(ctx);
13507
13508        ext2fs_close(fs);
13509        ctx->fs = NULL;
13510        free(ctx->filesystem_name);
13511        free(ctx->journal_name);
13512        e2fsck_free_context(ctx);
13513
13514        return exit_value;
13515}
13516