119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * pass3.c -- pass #3 of e2fsck: Check for directory connectivity 319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999 Theodore Ts'o. 519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %Begin-Header% 719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This file may be redistributed under the terms of the GNU Public 819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * License. 919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * %End-Header% 103984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * 1119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Pass #3 assures that all directories are connected to the 1219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * filesystem tree, using the following algorithm: 1319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 1419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * First, the root directory is checked to make sure it exists; if 1519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * not, e2fsck will offer to create a new one. It is then marked as 1619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * "done". 173984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * 1819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Then, pass3 interates over all directory inodes; for each directory 1919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * it attempts to trace up the filesystem tree, using dirinfo.parent 2019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * until it reaches a directory which has been marked "done". If it 2119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * can not do so, then the directory must be disconnected, and e2fsck 2219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * will offer to reconnect it to /lost+found. While it is chasing 2319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * parent pointers up the filesystem tree, if pass3 sees a directory 2419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * twice, then it has detected a filesystem loop, and it will again 2519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * offer to reconnect the directory to /lost+found in to break the 2619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * filesystem loop. 273984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * 2819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to 2919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * reconnect inodes to /lost+found; this subroutine is also used by 3019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * pass 4. e2fsck_reconnect_file() calls get_lost_and_found(), which 3119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * is responsible for creating /lost+found if it does not exist. 3219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 3319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Pass 3 frees the following data structures: 3419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * - The dirinfo directory information cache. 3519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 3619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 3719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef HAVE_ERRNO_H 3819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include <errno.h> 3919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 4019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 4119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "e2fsck.h" 4219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#include "problem.h" 4319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 4419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void check_root(e2fsck_t ctx); 4519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int check_directory(e2fsck_t ctx, ext2_ino_t ino, 4619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct problem_context *pctx); 4719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void fix_dotdot(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent); 4819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 4919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic ext2fs_inode_bitmap inode_loop_detect = 0; 5019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic ext2fs_inode_bitmap inode_done_map = 0; 513984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 5219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectvoid e2fsck_pass3(e2fsck_t ctx) 5319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 5419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_filsys fs = ctx->fs; 5519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct dir_info_iter *iter; 5619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef RESOURCE_TRACK 5719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct resource_track rtrack; 5819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 5919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct problem_context pctx; 6019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct dir_info *dir; 6119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project unsigned long maxdirs, count; 6219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 633984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt init_resource_track(&rtrack, ctx->fs->io); 6419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project clear_problem_context(&pctx); 6519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 6619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#ifdef MTRACE 6719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project mtrace_print("Pass 3"); 6819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 6919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 7019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!(ctx->options & E2F_OPT_PREEN)) 7119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(ctx, PR_3_PASS_HEADER, &pctx); 7219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 7319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 7419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Allocate some bitmaps to do loop detection. 7519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 7619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.errcode = ext2fs_allocate_inode_bitmap(fs, _("inode done bitmap"), 7719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project &inode_done_map); 7819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (pctx.errcode) { 7919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.num = 2; 8019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx); 8119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ctx->flags |= E2F_FLAG_ABORT; 8219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto abort_exit; 8319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 843984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt print_resource_track(ctx, _("Peak memory"), &ctx->global_rtrack, NULL); 8519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 8619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project check_root(ctx); 8719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 8819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto abort_exit; 8919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 9019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO); 9119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 9219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project maxdirs = e2fsck_get_num_dirinfo(ctx); 9319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project count = 1; 9419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 9519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ctx->progress) 9619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((ctx->progress)(ctx, 3, 0, maxdirs)) 9719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto abort_exit; 983984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 9919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project iter = e2fsck_dir_info_iter_begin(ctx); 10019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project while ((dir = e2fsck_dir_info_iter(ctx, iter)) != 0) { 10119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 10219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto abort_exit; 10319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ctx->progress && (ctx->progress)(ctx, 3, count++, maxdirs)) 10419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto abort_exit; 10519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino)) 10619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (check_directory(ctx, dir->ino, &pctx)) 10719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project goto abort_exit; 10819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 10919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e2fsck_dir_info_iter_end(ctx, iter); 11019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 11119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 11219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Force the creation of /lost+found if not present 11319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 11419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((ctx->flags & E2F_OPT_READONLY) == 0) 11519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e2fsck_get_lost_and_found(ctx, 1); 11619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 11719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 11819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * If there are any directories that need to be indexed or 11919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * optimized, do it here. 12019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 12119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e2fsck_rehash_directories(ctx); 1223984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 12319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectabort_exit: 12419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e2fsck_free_dir_info(ctx); 12519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (inode_loop_detect) { 12619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_free_inode_bitmap(inode_loop_detect); 12719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project inode_loop_detect = 0; 12819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 12919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (inode_done_map) { 13019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_free_inode_bitmap(inode_done_map); 13119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project inode_done_map = 0; 13219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 13319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 1343984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt print_resource_track(ctx, _("Pass 3"), &rtrack, ctx->fs->io); 13519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 13619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 13719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 13819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This makes sure the root inode is present; if not, we ask if the 13919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * user wants us to create it. Not creating it is a fatal error. 14019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 14119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void check_root(e2fsck_t ctx) 14219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 14319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_filsys fs = ctx->fs; 14419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t blk; 14519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode inode; 14619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char * block; 14719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct problem_context pctx; 1483984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 14919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project clear_problem_context(&pctx); 1503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 15119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) { 15219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 15319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * If the root inode is not a directory, die here. The 15419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * user must have answered 'no' in pass1 when we 15519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * offered to clear it. 15619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 15719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map, 15819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project EXT2_ROOT_INO))) { 15919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx); 16019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ctx->flags |= E2F_FLAG_ABORT; 16119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 16219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 16319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 16419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 16519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) { 16619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx); 16719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ctx->flags |= E2F_FLAG_ABORT; 16819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 16919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 17019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 17119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e2fsck_read_bitmaps(ctx); 1723984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 17319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 17419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * First, find a free block 17519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 17619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk); 17719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (pctx.errcode) { 17819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.str = "ext2fs_new_block"; 17919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx); 18019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ctx->flags |= E2F_FLAG_ABORT; 18119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 18219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 18319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_mark_block_bitmap(ctx->block_found_map, blk); 18419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_mark_block_bitmap(fs->block_map, blk); 18519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_mark_bb_dirty(fs); 18619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 18719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 18819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Now let's create the actual data block for the inode 18919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 19019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, 19119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project &block); 19219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (pctx.errcode) { 19319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.str = "ext2fs_new_dir_block"; 19419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx); 19519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ctx->flags |= E2F_FLAG_ABORT; 19619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 19719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 19819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 19919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.errcode = ext2fs_write_dir_block(fs, blk, block); 20019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (pctx.errcode) { 20119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.str = "ext2fs_write_dir_block"; 20219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx); 20319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ctx->flags |= E2F_FLAG_ABORT; 20419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 20519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 20619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_free_mem(&block); 20719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 20819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 20919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Set up the inode structure 21019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 21119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project memset(&inode, 0, sizeof(inode)); 21219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project inode.i_mode = 040755; 21319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project inode.i_size = fs->blocksize; 21419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project inode.i_atime = inode.i_ctime = inode.i_mtime = ctx->now; 21519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project inode.i_links_count = 2; 2163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2fs_iblk_set(fs, &inode, 1); 21719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project inode.i_block[0] = blk; 21819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 21919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 22019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Write out the inode. 22119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 22219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.errcode = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode); 22319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (pctx.errcode) { 22419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.str = "ext2fs_write_inode"; 22519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx); 22619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ctx->flags |= E2F_FLAG_ABORT; 22719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 22819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 2293984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 23019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 23119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Miscellaneous bookkeeping... 23219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 23319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO); 23419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2); 23519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2); 23619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 23719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO); 23819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO); 23919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO); 24019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_mark_ib_dirty(fs); 24119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 24219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 24319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 24419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This subroutine is responsible for making sure that a particular 24519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * directory is connected to the root; if it isn't we trace it up as 24619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * far as we can go, and then offer to connect the resulting parent to 24719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * the lost+found. We have to do loop detection; if we ever discover 24819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * a loop, we treat that as a disconnected directory and offer to 24919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * reparent it to lost+found. 2503984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt * 25119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * However, loop detection is expensive, because for very large 25219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * filesystems, the inode_loop_detect bitmap is huge, and clearing it 25319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * is non-trivial. Loops in filesystems are also a rare error case, 25419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * and we shouldn't optimize for error cases. So we try two passes of 25519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * the algorithm. The first time, we ignore loop detection and merely 25619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * increment a counter; if the counter exceeds some extreme threshold, 25719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * then we try again with the loop detection bitmap enabled. 25819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 25919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int check_directory(e2fsck_t ctx, ext2_ino_t dir, 26019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct problem_context *pctx) 26119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 26219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_filsys fs = ctx->fs; 26319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_ino_t ino = dir, parent; 26419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int loop_pass = 0, parent_count = 0; 26519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 26619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project while (1) { 26719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 26819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Mark this inode as being "done"; by the time we 26919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * return from this function, the inode we either be 27019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * verified as being connected to the directory tree, 27119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * or we will have offered to reconnect this to 27219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * lost+found. 27319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * 27419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * If it was marked done already, then we've reached a 27519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * parent we've already checked. 27619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 27719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ext2fs_mark_inode_bitmap(inode_done_map, ino)) 27819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project break; 27919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 28019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (e2fsck_dir_info_get_parent(ctx, ino, &parent)) { 28119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(ctx, PR_3_NO_DIRINFO, pctx); 28219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 28319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 28419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 28519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 28619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * If this directory doesn't have a parent, or we've 28719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * seen the parent once already, then offer to 28819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * reparent it to lost+found 28919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 29019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!parent || 2913984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt (loop_pass && 29219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (ext2fs_test_inode_bitmap(inode_loop_detect, 29319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project parent)))) { 29419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx->ino = ino; 29519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) { 29619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (e2fsck_reconnect_file(ctx, pctx->ino)) 29719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_unmark_valid(fs); 29819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project else { 2993984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fix_dotdot(ctx, pctx->ino, 30019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ctx->lost_and_found); 30119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project parent = ctx->lost_and_found; 30219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 30319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 30419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project break; 30519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 30619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ino = parent; 30719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (loop_pass) { 30819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_mark_inode_bitmap(inode_loop_detect, ino); 30919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } else if (parent_count++ > 2048) { 31019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 31119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * If we've run into a path depth that's 31219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * greater than 2048, try again with the inode 31319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * loop bitmap turned on and start from the 31419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * top. 31519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 31619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project loop_pass = 1; 31719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (inode_loop_detect) 31819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_clear_inode_bitmap(inode_loop_detect); 31919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project else { 32019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx->errcode = ext2fs_allocate_inode_bitmap(fs, _("inode loop detection bitmap"), &inode_loop_detect); 32119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (pctx->errcode) { 32219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx->num = 1; 3233984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt fix_problem(ctx, 32419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project PR_3_ALLOCATE_IBITMAP_ERROR, pctx); 32519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ctx->flags |= E2F_FLAG_ABORT; 32619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return -1; 32719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 32819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 32919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ino = dir; 33019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 33119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 33219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 33319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 33419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Make sure that .. and the parent directory are the same; 33519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * offer to fix it if not. 33619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 33719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx->ino = dir; 33819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (e2fsck_dir_info_get_dotdot(ctx, dir, &pctx->ino2) || 33919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e2fsck_dir_info_get_parent(ctx, dir, &pctx->dir)) { 34019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(ctx, PR_3_NO_DIRINFO, pctx); 34119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 34219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 34319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (pctx->ino2 != pctx->dir) { 34419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx)) 34519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_dotdot(ctx, dir, pctx->dir); 34619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 34719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 34819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 34919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 35019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 35119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This routine gets the lost_and_found inode, making it a directory 35219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * if necessary 35319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 35419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectext2_ino_t e2fsck_get_lost_and_found(e2fsck_t ctx, int fix) 35519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 35619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_filsys fs = ctx->fs; 35719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_ino_t ino; 35819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t blk; 35919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 36019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode inode; 36119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char * block; 36219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project static const char name[] = "lost+found"; 36319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct problem_context pctx; 36419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 36519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ctx->lost_and_found) 36619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return ctx->lost_and_found; 36719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 36819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project clear_problem_context(&pctx); 3693984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 37019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name, 37119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project sizeof(name)-1, 0, &ino); 37219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval && !fix) 37319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 37419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!retval) { 37519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) { 37619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ctx->lost_and_found = ino; 37719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return ino; 37819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 3793984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 38019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* Lost+found isn't a directory! */ 38119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!fix) 38219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 38319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.ino = ino; 38419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx)) 38519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 38619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 38719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* OK, unlink the old /lost+found file. */ 38819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0); 38919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (pctx.errcode) { 39019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.str = "ext2fs_unlink"; 39119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx); 39219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 39319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 39419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (void) e2fsck_dir_info_set_parent(ctx, ino, 0); 39519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e2fsck_adjust_inode_count(ctx, ino, -1); 39619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } else if (retval != EXT2_ET_FILE_NOT_FOUND) { 39719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.errcode = retval; 39819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx); 39919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 40019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0)) 40119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 40219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 40319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 40419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Read the inode and block bitmaps in; we'll be messing with 40519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * them. 40619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 40719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e2fsck_read_bitmaps(ctx); 4083984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 40919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 41019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * First, find a free block 41119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 41219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk); 41319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) { 41419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.errcode = retval; 41519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx); 41619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 41719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 41819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_mark_block_bitmap(ctx->block_found_map, blk); 41919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_block_alloc_stats(fs, blk, +1); 42019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 42119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 42219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Next find a free inode. 42319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 42419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040700, 42519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ctx->inode_used_map, &ino); 42619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) { 42719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.errcode = retval; 42819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx); 42919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 43019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 43119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino); 43219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino); 43319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_inode_alloc_stats2(fs, ino, +1, 1); 43419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 43519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 43619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Now let's create the actual data block for the inode 43719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 43819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block); 43919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) { 44019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.errcode = retval; 44119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx); 44219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 44319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 44419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 44519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_write_dir_block(fs, blk, block); 44619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_free_mem(&block); 44719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) { 44819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.errcode = retval; 44919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx); 45019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 45119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 45219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 45319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 45419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Set up the inode structure 45519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 45619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project memset(&inode, 0, sizeof(inode)); 45719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project inode.i_mode = 040700; 45819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project inode.i_size = fs->blocksize; 45919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project inode.i_atime = inode.i_ctime = inode.i_mtime = ctx->now; 46019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project inode.i_links_count = 2; 4613984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2fs_iblk_set(fs, &inode, 1); 46219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project inode.i_block[0] = blk; 46319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 46419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 46519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Next, write out the inode. 46619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 46719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.errcode = ext2fs_write_new_inode(fs, ino, &inode); 46819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (pctx.errcode) { 46919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.str = "ext2fs_write_inode"; 47019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx); 47119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 47219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 47319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 47419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Finally, create the directory link 47519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 47619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, EXT2_FT_DIR); 47719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (pctx.errcode) { 47819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.str = "ext2fs_link"; 47919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx); 48019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 48119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 48219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 48319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 48419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Miscellaneous bookkeeping that needs to be kept straight. 48519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 48619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO); 48719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e2fsck_adjust_inode_count(ctx, EXT2_ROOT_INO, 1); 48819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_icount_store(ctx->inode_count, ino, 2); 48919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_icount_store(ctx->inode_link_info, ino, 2); 49019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ctx->lost_and_found = ino; 49119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if 0 49219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project printf("/lost+found created; inode #%lu\n", ino); 49319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 49419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return ino; 49519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 49619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 49719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 49819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * This routine will connect a file to lost+found 49919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 50019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectint e2fsck_reconnect_file(e2fsck_t ctx, ext2_ino_t ino) 50119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 50219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_filsys fs = ctx->fs; 50319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 50419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char name[80]; 50519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct problem_context pctx; 50619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode inode; 50719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int file_type = 0; 50819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 50919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project clear_problem_context(&pctx); 51019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.ino = ino; 51119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 51219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!ctx->bad_lost_and_found && !ctx->lost_and_found) { 51319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (e2fsck_get_lost_and_found(ctx, 1) == 0) 51419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ctx->bad_lost_and_found++; 51519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 51619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ctx->bad_lost_and_found) { 51719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(ctx, PR_3_NO_LPF, &pctx); 51819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 1; 51919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 5203984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 52119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project sprintf(name, "#%u", ino); 52219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (ext2fs_read_inode(fs, ino, &inode) == 0) 52319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project file_type = ext2_file_type(inode.i_mode); 52419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_link(fs, ctx->lost_and_found, name, ino, file_type); 52519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval == EXT2_ET_DIR_NO_SPACE) { 52619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx)) 52719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 1; 5283984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt retval = e2fsck_expand_directory(ctx, ctx->lost_and_found, 52919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 1, 0); 53019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) { 53119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.errcode = retval; 53219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx); 53319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 1; 53419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 53519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_link(fs, ctx->lost_and_found, name, 53619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ino, file_type); 53719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 53819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) { 53919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.errcode = retval; 54019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx); 54119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 1; 54219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 54319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e2fsck_adjust_inode_count(ctx, ino, 1); 54419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 54519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 54619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 54719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 54819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 54919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Utility routine to adjust the inode counts on an inode. 55019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 55119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t e2fsck_adjust_inode_count(e2fsck_t ctx, ext2_ino_t ino, int adj) 55219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 55319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_filsys fs = ctx->fs; 55419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 55519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode inode; 5563984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 55719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!ino) 55819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 55919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 56019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_read_inode(fs, ino, &inode); 56119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 56219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 56319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 56419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if 0 56519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project printf("Adjusting link count for inode %lu by %d (from %d)\n", ino, adj, 56619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project inode.i_links_count); 56719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 56819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 56919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (adj == 1) { 57019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_icount_increment(ctx->inode_count, ino, 0); 57119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (inode.i_links_count == (__u16) ~0) 57219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 57319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_icount_increment(ctx->inode_link_info, ino, 0); 57419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project inode.i_links_count++; 57519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } else if (adj == -1) { 57619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_icount_decrement(ctx->inode_count, ino, 0); 57719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (inode.i_links_count == 0) 57819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 57919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_icount_decrement(ctx->inode_link_info, ino, 0); 58019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project inode.i_links_count--; 58119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 5823984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 58319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_write_inode(fs, ino, &inode); 58419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 58519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 58619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 58719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 58819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 58919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 59019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 59119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Fix parent --- this routine fixes up the parent of a directory. 59219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 59319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstruct fix_dotdot_struct { 59419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_filsys fs; 59519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_ino_t parent; 59619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int done; 59719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e2fsck_t ctx; 59819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}; 59919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 60019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int fix_dotdot_proc(struct ext2_dir_entry *dirent, 60119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int offset EXT2FS_ATTR((unused)), 60219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int blocksize EXT2FS_ATTR((unused)), 60319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char *buf EXT2FS_ATTR((unused)), 60419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project void *priv_data) 60519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 60619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data; 60719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 60819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct problem_context pctx; 60919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 61019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if ((dirent->name_len & 0xFF) != 2) 61119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 61219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (strncmp(dirent->name, "..", 2)) 61319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 61419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 61519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project clear_problem_context(&pctx); 6163984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 61719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = e2fsck_adjust_inode_count(fp->ctx, dirent->inode, -1); 61819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) { 61919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.errcode = retval; 62019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx); 62119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 62219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = e2fsck_adjust_inode_count(fp->ctx, fp->parent, 1); 62319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) { 62419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.errcode = retval; 62519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx); 62619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 62719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project dirent->inode = fp->parent; 62819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (fp->ctx->fs->super->s_feature_incompat & 62919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project EXT2_FEATURE_INCOMPAT_FILETYPE) 6303984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt dirent->name_len = (dirent->name_len & 0xFF) | 63119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (EXT2_FT_DIR << 8); 63219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project else 63319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project dirent->name_len = dirent->name_len & 0xFF; 63419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 63519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fp->done++; 63619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return DIRENT_ABORT | DIRENT_CHANGED; 63719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 63819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 63919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic void fix_dotdot(e2fsck_t ctx, ext2_ino_t ino, ext2_ino_t parent) 64019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 64119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_filsys fs = ctx->fs; 64219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 64319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct fix_dotdot_struct fp; 64419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct problem_context pctx; 64519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 64619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fp.fs = fs; 64719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fp.parent = parent; 64819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fp.done = 0; 64919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fp.ctx = ctx; 65019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 65119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#if 0 65219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project printf("Fixing '..' of inode %lu to be %lu...\n", ino, parent); 65319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project#endif 6543984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 65519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project clear_problem_context(&pctx); 65619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.ino = ino; 65719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_dir_iterate(fs, ino, DIRENT_FLAG_INCLUDE_EMPTY, 65819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 0, fix_dotdot_proc, &fp); 65919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval || !fp.done) { 66019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project pctx.errcode = retval; 66119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR : 66219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project PR_3_FIX_PARENT_NOFIND, &pctx); 66319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_unmark_valid(fs); 66419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 66519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project (void) e2fsck_dir_info_set_dotdot(ctx, ino, parent); 66619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (e2fsck_dir_info_set_parent(ctx, ino, ctx->lost_and_found)) 66719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project fix_problem(ctx, PR_3_NO_DIRINFO, &pctx); 66819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 66919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return; 67019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 67119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 67219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project/* 67319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * These routines are responsible for expanding a /lost+found if it is 67419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * too small. 67519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 67619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 67719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstruct expand_dir_struct { 67819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int num; 67919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int guaranteed_size; 68019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int newblocks; 68119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int last_block; 68219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t err; 68319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e2fsck_t ctx; 68419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project}; 68519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 68619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projectstatic int expand_dir_proc(ext2_filsys fs, 68719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t *blocknr, 68819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e2_blkcnt_t blockcnt, 68919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t ref_block EXT2FS_ATTR((unused)), 69019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int ref_offset EXT2FS_ATTR((unused)), 69119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project void *priv_data) 69219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 69319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data; 69419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project blk_t new_blk; 69519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project static blk_t last_blk = 0; 69619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project char *block; 69719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 69819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e2fsck_t ctx; 69919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 70019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ctx = es->ctx; 7013984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 70219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (es->guaranteed_size && blockcnt >= es->guaranteed_size) 70319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return BLOCK_ABORT; 70419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 70519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (blockcnt > 0) 70619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project es->last_block = blockcnt; 70719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (*blocknr) { 70819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project last_blk = *blocknr; 70919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 71019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 71119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map, 71219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project &new_blk); 71319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) { 71419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project es->err = retval; 71519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return BLOCK_ABORT; 71619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 71719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (blockcnt > 0) { 71819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_new_dir_block(fs, 0, 0, &block); 71919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) { 72019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project es->err = retval; 72119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return BLOCK_ABORT; 72219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 72319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project es->num--; 72419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_write_dir_block(fs, new_blk, block); 72519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } else { 72619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_get_mem(fs->blocksize, &block); 72719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) { 72819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project es->err = retval; 72919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return BLOCK_ABORT; 73019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 73119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project memset(block, 0, fs->blocksize); 73219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = io_channel_write_blk(fs->io, new_blk, 1, block); 7333984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt } 73419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) { 73519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project es->err = retval; 73619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return BLOCK_ABORT; 73719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project } 73819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_free_mem(&block); 73919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project *blocknr = new_blk; 74019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk); 74119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2fs_block_alloc_stats(fs, new_blk, +1); 74219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project es->newblocks++; 7433984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 74419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (es->num == 0) 74519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return (BLOCK_CHANGED | BLOCK_ABORT); 74619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project else 74719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return BLOCK_CHANGED; 74819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 74919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 75019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Projecterrcode_t e2fsck_expand_directory(e2fsck_t ctx, ext2_ino_t dir, 75119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project int num, int guaranteed_size) 75219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project{ 75319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project ext2_filsys fs = ctx->fs; 75419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project errcode_t retval; 75519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct expand_dir_struct es; 75619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project struct ext2_inode inode; 7573984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 75819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (!(fs->flags & EXT2_FLAG_RW)) 75919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return EXT2_ET_RO_FILSYS; 76019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 76119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 76219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Read the inode and block bitmaps in; we'll be messing with 76319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * them. 76419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 76519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e2fsck_read_bitmaps(ctx); 76619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 76719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_check_directory(fs, dir); 76819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 76919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 7703984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 77119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project es.num = num; 77219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project es.guaranteed_size = guaranteed_size; 77319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project es.last_block = 0; 77419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project es.err = 0; 77519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project es.newblocks = 0; 77619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project es.ctx = ctx; 7773984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 77819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_block_iterate2(fs, dir, BLOCK_FLAG_APPEND, 77919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 0, expand_dir_proc, &es); 78019dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 78119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (es.err) 78219dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return es.err; 78319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 78419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project /* 78519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project * Update the size and block count fields in the inode. 78619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project */ 78719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project retval = ext2fs_read_inode(fs, dir, &inode); 78819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project if (retval) 78919dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return retval; 7903984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt 79119dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project inode.i_size = (es.last_block + 1) * fs->blocksize; 7923984b61df41c68966bdfbb2a5e5a45ef4b9a536cDmitry Shmidt ext2fs_iblk_add_blocks(fs, &inode, es.newblocks); 79319dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 79419dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project e2fsck_write_inode(ctx, dir, &inode, "expand_directory"); 79519dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 79619dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project return 0; 79719dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project} 79819dacda2b02bb08c0ffb649f84526b249c749279The Android Open Source Project 799