pass3.c revision 5596defa1e212242c1bf1b028139143fbb7777a0
13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * pass3.c -- pass #3 of e2fsck: Check for directory connectivity 33839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o. 521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * 621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * %Begin-Header% 721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * This file may be redistributed under the terms of the GNU Public 821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * License. 921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * %End-Header% 103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Pass #3 assures that all directories are connected to the 123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * filesystem tree, using the following algorithm: 133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * First, the root directory is checked to make sure it exists; if 153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * not, e2fsck will offer to create a new one. It is then marked as 163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * "done". 173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Then, pass3 interates over all directory inodes; for each directory 193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * it attempts to trace up the filesystem tree, using dirinfo.parent 203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * until it reaches a directory which has been marked "done". If it 213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * can not do so, then the directory must be disconnected, and e2fsck 223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * will offer to reconnect it to /lost+found. While it is chasing 233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * parent pointers up the filesystem tree, if pass3 sees a directory 243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * twice, then it has detected a filesystem loop, and it will again 253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * offer to reconnect the directory to /lost+found in to break the 263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * filesystem loop. 273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 2808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o * Pass 3 also contains the subroutine, e2fsck_reconnect_file() to 2908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o * reconnect inodes to /lost+found; this subroutine is also used by 3008b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o * pass 4. e2fsck_reconnect_file() calls get_lost_and_found(), which 3108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o * is responsible for creating /lost+found if it does not exist. 323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * 333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Pass 3 frees the following data structures: 343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * - The dirinfo directory information cache. 353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 3750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#ifdef HAVE_ERRNO_H 3850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <errno.h> 3950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif 403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "e2fsck.h" 4221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#include "problem.h" 433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 441b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic void check_root(e2fsck_t ctx); 451b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic void check_directory(e2fsck_t ctx, struct dir_info *dir, 4621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct problem_context *pctx); 471b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic ino_t get_lost_and_found(e2fsck_t ctx); 481b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ino_t parent); 491b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic errcode_t adjust_inode_count(e2fsck_t ctx, ino_t ino, int adj); 501b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic errcode_t expand_directory(e2fsck_t ctx, ino_t dir); 513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic ino_t lost_and_found = 0; 533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int bad_lost_and_found = 0; 543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 55a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'ostatic ext2fs_inode_bitmap inode_loop_detect = 0; 56a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'ostatic ext2fs_inode_bitmap inode_done_map = 0; 573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'ovoid e2fsck_pass3(e2fsck_t ctx) 593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 601b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int i; 628bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#ifdef RESOURCE_TRACK 633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct resource_track rtrack; 648bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#endif 6521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct problem_context pctx; 6621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct dir_info *dir; 677f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o unsigned long maxdirs, count; 68f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o 698bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#ifdef RESOURCE_TRACK 703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o init_resource_track(&rtrack); 718bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#endif 723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 731b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o clear_problem_context(&pctx); 741b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#ifdef MTRACE 763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o mtrace_print("Pass 3"); 773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif 783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 791b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (!(ctx->options & E2F_OPT_PREEN)) 801b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_PASS_HEADER, &pctx); 813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Allocate some bitmaps to do loop detection. 843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 851b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = ext2fs_allocate_inode_bitmap(fs, 861b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o "inode loop detection bitmap", &inode_loop_detect); 871b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx.errcode) { 881b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.num = 1; 891b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx); 9008b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 91a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o goto abort_exit; 923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 931b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = ext2fs_allocate_inode_bitmap(fs, "inode done bitmap", 941b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o &inode_done_map); 951b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx.errcode) { 961b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.num = 2; 971b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_ALLOCATE_IBITMAP_ERROR, &pctx); 9808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 99a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o goto abort_exit; 1003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1018bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#ifdef RESOURCE_TRACK 1025596defa1e212242c1bf1b028139143fbb7777a0Theodore Ts'o if (ctx->options & E2F_OPT_TIME) { 1035596defa1e212242c1bf1b028139143fbb7777a0Theodore Ts'o e2fsck_clear_progbar(ctx); 1041b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o print_resource_track("Peak memory", &ctx->global_rtrack); 1055596defa1e212242c1bf1b028139143fbb7777a0Theodore Ts'o } 1068bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#endif 1073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1081b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o check_root(ctx); 109a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o if (ctx->flags & E2F_FLAG_SIGNAL_MASK) 110a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o goto abort_exit; 11108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o 112f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2fs_mark_inode_bitmap(inode_done_map, EXT2_ROOT_INO); 1133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1147f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o maxdirs = e2fsck_get_num_dirinfo(ctx); 115f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o count = 1; 116f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o 117f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o if (ctx->progress) 1187f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o if ((ctx->progress)(ctx, 3, 0, maxdirs)) 119f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o goto abort_exit; 120f75c28de4731c2cd09f6ca1a23e25c968a1edc2fTheodore Ts'o 12108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o for (i=0; (dir = e2fsck_dir_info_iter(ctx, &i)) != 0;) { 122f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o if (ctx->progress) 1237f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o if ((ctx->progress)(ctx, 3, count++, maxdirs)) 124a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o goto abort_exit; 1251b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, dir->ino)) 1261b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o check_directory(ctx, dir, &pctx); 1273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 128a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o 1295a679c8fb15540f86fc2eae3117412adc6ecbb33Theodore Ts'o /* 1305a679c8fb15540f86fc2eae3117412adc6ecbb33Theodore Ts'o * Force the creation of /lost+found if not present 1315a679c8fb15540f86fc2eae3117412adc6ecbb33Theodore Ts'o */ 1325a679c8fb15540f86fc2eae3117412adc6ecbb33Theodore Ts'o if ((ctx->flags & E2F_OPT_READONLY) == 0) 1335a679c8fb15540f86fc2eae3117412adc6ecbb33Theodore Ts'o get_lost_and_found(ctx); 1345a679c8fb15540f86fc2eae3117412adc6ecbb33Theodore Ts'o 135a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'oabort_exit: 13608b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_free_dir_info(ctx); 137a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o if (inode_loop_detect) 138a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o ext2fs_free_inode_bitmap(inode_loop_detect); 139a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o if (inode_done_map) 140a02ce9df5ff5db2982462aec7162f7142dc18131Theodore Ts'o ext2fs_free_inode_bitmap(inode_done_map); 1418bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#ifdef RESOURCE_TRACK 1425596defa1e212242c1bf1b028139143fbb7777a0Theodore Ts'o if (ctx->options & E2F_OPT_TIME2) { 1435596defa1e212242c1bf1b028139143fbb7777a0Theodore Ts'o e2fsck_clear_progbar(ctx); 1441b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o print_resource_track("Pass 3", &rtrack); 1455596defa1e212242c1bf1b028139143fbb7777a0Theodore Ts'o } 1468bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#endif 1473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 1483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 1503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This makes sure the root inode is present; if not, we ask if the 1513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * user wants us to create it. Not creating it is a fatal error. 1523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1531b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic void check_root(e2fsck_t ctx) 1543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 1551b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 1563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o blk_t blk; 1573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_inode inode; 1583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * block; 1591b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o struct problem_context pctx; 1603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1611b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o clear_problem_context(&pctx); 1621b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 1631b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (ext2fs_test_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO)) { 1643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 16508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o * If the root inode is not a directory, die here. The 1663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * user must have answered 'no' in pass1 when we 1673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * offered to clear it. 1683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1691b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (!(ext2fs_test_inode_bitmap(ctx->inode_dir_map, 170f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o EXT2_ROOT_INO))) { 171f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o fix_problem(ctx, PR_3_ROOT_NOT_DIR_ABORT, &pctx); 172f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 173f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o } 1743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return; 1753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 177f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o if (!fix_problem(ctx, PR_3_NO_ROOT_INODE, &pctx)) { 178f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o fix_problem(ctx, PR_3_NO_ROOT_INODE_ABORT, &pctx); 179f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 180f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o return; 181f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o } 1823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 183f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o e2fsck_read_bitmaps(ctx); 1843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 1863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * First, find a free block 1873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 1881b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk); 1891b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx.errcode) { 1901b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.str = "ext2fs_new_block"; 1911b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx); 19208b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 19308b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 1943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 1951b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_mark_block_bitmap(ctx->block_found_map, blk); 196f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2fs_mark_block_bitmap(fs->block_map, blk); 1973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ext2fs_mark_bb_dirty(fs); 1983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 1993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 2003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Now let's create the actual data block for the inode 2013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 2021b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = ext2fs_new_dir_block(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, 2031b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o &block); 2041b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx.errcode) { 2051b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.str = "ext2fs_new_dir_block"; 2061b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx); 20708b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 20808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 2093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2111b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = ext2fs_write_dir_block(fs, blk, block); 2121b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx.errcode) { 2131b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.str = "ext2fs_write_dir_block"; 2141b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx); 21508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 21608b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 2173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 21808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ext2fs_free_mem((void **) &block); 2193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 2213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Set up the inode structure 2223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 2233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset(&inode, 0, sizeof(inode)); 2243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_mode = 040755; 2253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_size = fs->blocksize; 2263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_atime = inode.i_ctime = inode.i_mtime = time(0); 2273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_links_count = 2; 2283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_blocks = fs->blocksize / 512; 2293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_block[0] = blk; 2303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 2323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Write out the inode. 2333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 2341b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = ext2fs_write_inode(fs, EXT2_ROOT_INO, &inode); 2351b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx.errcode) { 2361b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.str = "ext2fs_write_inode"; 2371b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_CREATE_ROOT_ERROR, &pctx); 23808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ctx->flags |= E2F_FLAG_ABORT; 23908b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o return; 2403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 2413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 2433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Miscellaneous bookkeeping... 2443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 24508b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_add_dir_info(ctx, EXT2_ROOT_INO, EXT2_ROOT_INO); 2461b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_store(ctx->inode_count, EXT2_ROOT_INO, 2); 2471b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_store(ctx->inode_link_info, EXT2_ROOT_INO, 2); 2483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2491b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_mark_inode_bitmap(ctx->inode_used_map, EXT2_ROOT_INO); 2501b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_mark_inode_bitmap(ctx->inode_dir_map, EXT2_ROOT_INO); 251f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2fs_mark_inode_bitmap(fs->inode_map, EXT2_ROOT_INO); 2523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ext2fs_mark_ib_dirty(fs); 2533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 2543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 2563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This subroutine is responsible for making sure that a particular 2573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * directory is connected to the root; if it isn't we trace it up as 2583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * far as we can go, and then offer to connect the resulting parent to 2593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * the lost+found. We have to do loop detection; if we ever discover 2603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * a loop, we treat that as a disconnected directory and offer to 2613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * reparent it to lost+found. 2623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 2631b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic void check_directory(e2fsck_t ctx, struct dir_info *dir, 26421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct problem_context *pctx) 2653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 2661b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 26721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o struct dir_info *p = dir; 2683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 2697f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o if (!p) 2707f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o return; 2717f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o 272f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2fs_clear_inode_bitmap(inode_loop_detect); 2737f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o 2747f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o /* 2757f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o * Keep going until we find a parent which we've already 2767f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o * checked. We know it's either already connected to the 2777f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o * directory tree, or it isn't but the user has already told 2787f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o * us he doesn't want us to reconnect the disconnected 2797f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o * subtree. 2807f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o */ 2817f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o while (!ext2fs_test_inode_bitmap(inode_done_map, p->ino)) { 2823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 2833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Mark this inode as being "done"; by the time we 2843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * return from this function, the inode we either be 2853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * verified as being connected to the directory tree, 2863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * or we will have offered to reconnect this to 2873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * lost+found. 2883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 289f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2fs_mark_inode_bitmap(inode_done_map, p->ino); 2907f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o 2913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 2923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * If this directory doesn't have a parent, or we've 2933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * seen the parent once already, then offer to 2943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * reparent it to lost+found 2953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 2963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!p->parent || 297f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o (ext2fs_test_inode_bitmap(inode_loop_detect, 2987f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o p->parent))) { 2997f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o pctx->ino = p->ino; 3007f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o if (fix_problem(ctx, PR_3_UNCONNECTED_DIR, pctx)) { 3017f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o if (e2fsck_reconnect_file(ctx, p->ino)) 3027f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o ext2fs_unmark_valid(fs); 3037f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o else { 3047f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o p->parent = lost_and_found; 3057f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o fix_dotdot(ctx, p, lost_and_found); 3067f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o } 3077f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o } 3083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o break; 3097f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o } 310f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2fs_mark_inode_bitmap(inode_loop_detect, 3113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o p->parent); 3127f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o pctx->ino = p->parent; 31308b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o p = e2fsck_get_dir_info(ctx, p->parent); 3147f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o if (!p) { 3157f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o fix_problem(ctx, PR_3_NO_DIRINFO, pctx); 3167f813ba33711902f5e557da49f98622532e7556dTheodore Ts'o return; 3173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 31821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 3193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 3203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 3213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Make sure that .. and the parent directory are the same; 3223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * offer to fix it if not. 3233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 3243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (dir->parent != dir->dotdot) { 32521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx->ino = dir->ino; 32621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx->ino2 = dir->dotdot; 32721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o pctx->dir = dir->parent; 3281b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (fix_problem(ctx, PR_3_BAD_DOT_DOT, pctx)) 3291b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_dotdot(ctx, dir, dir->parent); 3303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 3323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 3333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 3343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This routine gets the lost_and_found inode, making it a directory 3353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * if necessary 3363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 3371b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'oino_t get_lost_and_found(e2fsck_t ctx) 3383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 3391b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 3403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ino_t ino; 3413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o blk_t blk; 3423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 3433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_inode inode; 3443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char * block; 34521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o const char name[] = "lost+found"; 3461b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o struct problem_context pctx; 3474a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o struct dir_info *dirinfo; 3483839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 3491b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o clear_problem_context(&pctx); 3501b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 35121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name, 35221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o sizeof(name)-1, 0, &ino); 3534a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o if (!retval) { 3544a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o if (ext2fs_test_inode_bitmap(ctx->inode_dir_map, ino)) 3554a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o return ino; 3564a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o /* Lost+found isn't a directory! */ 3574a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o pctx.ino = ino; 3584a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o if (!fix_problem(ctx, PR_3_LPF_NOTDIR, &pctx)) 3594a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o return 0; 3604a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o 361c54b3c3c99a5d3011f6f60934e90dae7f60b3b00Theodore Ts'o /* OK, unlink the old /lost+found file. */ 3624a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o pctx.errcode = ext2fs_unlink(fs, EXT2_ROOT_INO, name, ino, 0); 3634a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o if (pctx.errcode) { 3644a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o pctx.str = "ext2fs_unlink"; 3654a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx); 3664a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o return 0; 3674a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o } 3684a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o dirinfo = e2fsck_get_dir_info(ctx, ino); 3694a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o if (dirinfo) 3704a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o dirinfo->parent = 0; 3714a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o adjust_inode_count(ctx, ino, -1); 3724a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o } else if (retval != EXT2_ET_FILE_NOT_FOUND) { 3731b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = retval; 3741b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_ERR_FIND_LPF, &pctx); 3751b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o } 3761b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (!fix_problem(ctx, PR_3_NO_LF_DIR, 0)) 3773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 3783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 3793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 3803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Read the inode and block bitmaps in; we'll be messing with 3813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * them. 3823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 383f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o e2fsck_read_bitmaps(ctx); 3843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 3853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 3863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * First, find a free block 3873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 3881b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o retval = ext2fs_new_block(fs, 0, ctx->block_found_map, &blk); 3893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 3901b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = retval; 3911b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_ERR_LPF_NEW_BLOCK, &pctx); 3923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 3933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 3941b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_mark_block_bitmap(ctx->block_found_map, blk); 395f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2fs_mark_block_bitmap(fs->block_map, blk); 3963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ext2fs_mark_bb_dirty(fs); 3973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 3983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 3993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Next find a free inode. 4003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 4011b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o retval = ext2fs_new_inode(fs, EXT2_ROOT_INO, 040755, 4021b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ctx->inode_used_map, &ino); 4033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 4041b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = retval; 4051b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_ERR_LPF_NEW_INODE, &pctx); 4063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 4073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4081b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_mark_inode_bitmap(ctx->inode_used_map, ino); 4091b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_mark_inode_bitmap(ctx->inode_dir_map, ino); 410f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2fs_mark_inode_bitmap(fs->inode_map, ino); 4113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ext2fs_mark_ib_dirty(fs); 4123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 4143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Now let's create the actual data block for the inode 4153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 4163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_new_dir_block(fs, ino, EXT2_ROOT_INO, &block); 4173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 4181b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = retval; 4191b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_ERR_LPF_NEW_DIR_BLOCK, &pctx); 4203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 4213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 42350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o retval = ext2fs_write_dir_block(fs, blk, block); 42408b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ext2fs_free_mem((void **) &block); 4253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 4261b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = retval; 4271b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_ERR_LPF_WRITE_BLOCK, &pctx); 4283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 4293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 4323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Set up the inode structure 4333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 4343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset(&inode, 0, sizeof(inode)); 4353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_mode = 040755; 4363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_size = fs->blocksize; 4373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_atime = inode.i_ctime = inode.i_mtime = time(0); 4383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_links_count = 2; 4393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_blocks = fs->blocksize / 512; 4403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_block[0] = blk; 4413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 4433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Next, write out the inode. 4443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 4451b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = ext2fs_write_inode(fs, ino, &inode); 4461b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx.errcode) { 4471b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.str = "ext2fs_write_inode"; 4481b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx); 4493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 4503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 4523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Finally, create the directory link 4533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 4541b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = ext2fs_link(fs, EXT2_ROOT_INO, name, ino, 0); 4551b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (pctx.errcode) { 4561b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.str = "ext2fs_link"; 4571b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_CREATE_LPF_ERROR, &pctx); 4583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 4593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 4623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Miscellaneous bookkeeping that needs to be kept straight. 4633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 46408b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_add_dir_info(ctx, ino, EXT2_ROOT_INO); 4651b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o adjust_inode_count(ctx, EXT2_ROOT_INO, +1); 4661b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_store(ctx->inode_count, ino, 2); 4671b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_store(ctx->inode_link_info, ino, 2); 4683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#if 0 469f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o printf("/lost+found created; inode #%lu\n", ino); 4703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif 4713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return ino; 4723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 4733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 4743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 4753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * This routine will connect a file to lost+found 4763839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 47708b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'oint e2fsck_reconnect_file(e2fsck_t ctx, ino_t inode) 4783839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 4791b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 4803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 4813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char name[80]; 4821b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o struct problem_context pctx; 4831b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 4841b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o clear_problem_context(&pctx); 4851b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.ino = inode; 4861b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 4871b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (!bad_lost_and_found && !lost_and_found) { 4881b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o lost_and_found = get_lost_and_found(ctx); 4891b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (!lost_and_found) 4901b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o bad_lost_and_found++; 4911b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o } 4923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (bad_lost_and_found) { 4931b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_NO_LPF, &pctx); 4943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 1; 4953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 4961b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 497f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o sprintf(name, "#%lu", inode); 4983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_link(fs, lost_and_found, name, inode, 0); 4993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval == EXT2_ET_DIR_NO_SPACE) { 5001b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (!fix_problem(ctx, PR_3_EXPAND_LF_DIR, &pctx)) 5013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 1; 5021b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o retval = expand_directory(ctx, lost_and_found); 5033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 5041b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = retval; 5051b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_CANT_EXPAND_LPF, &pctx); 5063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 1; 5073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 5083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_link(fs, lost_and_found, name, inode, 0); 5093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 5103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 5111b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = retval; 5121b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, PR_3_CANT_RECONNECT, &pctx); 5133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 1; 5143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 5151b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o adjust_inode_count(ctx, inode, +1); 5163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 5183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 5193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 5213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Utility routine to adjust the inode counts on an inode. 5223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 5231b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic errcode_t adjust_inode_count(e2fsck_t ctx, ino_t ino, int adj) 5243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 5251b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 5263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 5273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_inode inode; 5283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!ino) 5303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 5313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_read_inode(fs, ino, &inode); 5333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 5343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 5353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#if 0 537f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o printf("Adjusting link count for inode %lu by %d (from %d)\n", ino, adj, 5383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_links_count); 5393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif 5403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_links_count += adj; 54221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o if (adj == 1) { 5431b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_increment(ctx->inode_count, ino, 0); 5441b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_increment(ctx->inode_link_info, ino, 0); 54521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } else { 5461b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_decrement(ctx->inode_count, ino, 0); 5471b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_icount_decrement(ctx->inode_link_info, ino, 0); 54821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o } 54921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o 5503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_write_inode(fs, ino, &inode); 5523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 5533839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 5543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 5563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 5573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 5593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Fix parent --- this routine fixes up the parent of a directory. 5603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 5613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostruct fix_dotdot_struct { 5623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ext2_filsys fs; 5633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ino_t parent; 5643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int done; 5651b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o e2fsck_t ctx; 5663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}; 5673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int fix_dotdot_proc(struct ext2_dir_entry *dirent, 5693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int offset, 5703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int blocksize, 5713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char *buf, 57254dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o void *priv_data) 5733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 57454dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o struct fix_dotdot_struct *fp = (struct fix_dotdot_struct *) priv_data; 5753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 5761b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o struct problem_context pctx; 5773839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 578b6f7983197fe217cf20862c93d72620be3b0fcecTheodore Ts'o if ((dirent->name_len & 0xFF) != 2) 5793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 5803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (strncmp(dirent->name, "..", 2)) 5813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 5823839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5831b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o clear_problem_context(&pctx); 5841b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 5851b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o retval = adjust_inode_count(fp->ctx, dirent->inode, -1); 5861b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (retval) { 5871b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = retval; 5881b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx); 5891b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o } 5901b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o retval = adjust_inode_count(fp->ctx, fp->parent, 1); 5911b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o if (retval) { 5921b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = retval; 5931b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(fp->ctx, PR_3_ADJUST_INODE, &pctx); 5941b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o } 5953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dirent->inode = fp->parent; 5963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 5973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fp->done++; 5983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return DIRENT_ABORT | DIRENT_CHANGED; 5993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 6003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6011b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic void fix_dotdot(e2fsck_t ctx, struct dir_info *dir, ino_t parent) 6023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 6031b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 6043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 6053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct fix_dotdot_struct fp; 6061b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o struct problem_context pctx; 6073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fp.fs = fs; 6093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fp.parent = parent; 6103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o fp.done = 0; 6111b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fp.ctx = ctx; 6123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#if 0 614f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o printf("Fixing '..' of inode %lu to be %lu...\n", dir->ino, parent); 6153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif 6163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_dir_iterate(fs, dir->ino, DIRENT_FLAG_INCLUDE_EMPTY, 6183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 0, fix_dotdot_proc, &fp); 6193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval || !fp.done) { 6201b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o clear_problem_context(&pctx); 6211b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.ino = dir->ino; 6221b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o pctx.errcode = retval; 6231b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o fix_problem(ctx, retval ? PR_3_FIX_PARENT_ERR : 6241b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o PR_3_FIX_PARENT_NOFIND, &pctx); 6253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ext2fs_unmark_valid(fs); 6263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 6273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o dir->dotdot = parent; 6283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return; 6303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 6313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/* 6333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * These routines are responsible for expanding a /lost+found if it is 6343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * too small. 6353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 6363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostruct expand_dir_struct { 6383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int done; 6393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t err; 6401b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o e2fsck_t ctx; 6413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}; 6423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ostatic int expand_dir_proc(ext2_filsys fs, 6443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o blk_t *blocknr, 6453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o int blockcnt, 64654dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o void *priv_data) 6473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 64854dc7ca2869897ae8cb81a9ab9880ebff11680bcTheodore Ts'o struct expand_dir_struct *es = (struct expand_dir_struct *) priv_data; 6493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o blk_t new_blk; 6503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o static blk_t last_blk = 0; 6513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o char *block; 6523839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 6531b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o e2fsck_t ctx; 6541b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o 6551b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ctx = es->ctx; 6563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6573839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (*blocknr) { 6583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o last_blk = *blocknr; 6593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 6603839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 6611b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o retval = ext2fs_new_block(fs, last_blk, ctx->block_found_map, 6621b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o &new_blk); 6633839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 6643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o es->err = retval; 6653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return BLOCK_ABORT; 6663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 6673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (blockcnt > 0) { 6683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_new_dir_block(fs, 0, 0, &block); 6693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 6703839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o es->err = retval; 6713839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return BLOCK_ABORT; 6723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 6733839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o es->done = 1; 674b8647faa3b0a7dfbb2456a7b37321ee4bbda651cTheodore Ts'o retval = ext2fs_write_dir_block(fs, new_blk, block); 6753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } else { 67608b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o retval = ext2fs_get_mem(fs->blocksize, (void **) &block); 67708b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o if (retval) { 67808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o es->err = retval; 6793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return BLOCK_ABORT; 6803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 6813839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o memset(block, 0, fs->blocksize); 682b8647faa3b0a7dfbb2456a7b37321ee4bbda651cTheodore Ts'o retval = io_channel_write_blk(fs->io, new_blk, 1, block); 6833839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 6843839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) { 6853839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o es->err = retval; 6863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return BLOCK_ABORT; 6873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o } 68808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o ext2fs_free_mem((void **) &block); 6893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o *blocknr = new_blk; 6901b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2fs_mark_block_bitmap(ctx->block_found_map, new_blk); 691f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o ext2fs_mark_block_bitmap(fs->block_map, new_blk); 6923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o ext2fs_mark_bb_dirty(fs); 6933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (es->done) 6943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return (BLOCK_CHANGED | BLOCK_ABORT); 6953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o else 6963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return BLOCK_CHANGED; 6973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 6983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 6991b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ostatic errcode_t expand_directory(e2fsck_t ctx, ino_t dir) 7003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{ 7011b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o ext2_filsys fs = ctx->fs; 7023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o errcode_t retval; 7033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct expand_dir_struct es; 7043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o struct ext2_inode inode; 7053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!(fs->flags & EXT2_FLAG_RW)) 7073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return EXT2_ET_RO_FILSYS; 7083839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 709b8647faa3b0a7dfbb2456a7b37321ee4bbda651cTheodore Ts'o /* 710b8647faa3b0a7dfbb2456a7b37321ee4bbda651cTheodore Ts'o * Read the inode and block bitmaps in; we'll be messing with 711b8647faa3b0a7dfbb2456a7b37321ee4bbda651cTheodore Ts'o * them. 712b8647faa3b0a7dfbb2456a7b37321ee4bbda651cTheodore Ts'o */ 713b8647faa3b0a7dfbb2456a7b37321ee4bbda651cTheodore Ts'o e2fsck_read_bitmaps(ctx); 714b8647faa3b0a7dfbb2456a7b37321ee4bbda651cTheodore Ts'o 7153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_check_directory(fs, dir); 7163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 7173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 7183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7193839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o es.done = 0; 7203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o es.err = 0; 7211b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o es.ctx = ctx; 7223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_block_iterate(fs, dir, BLOCK_FLAG_APPEND, 7243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 0, expand_dir_proc, &es); 7253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (es.err) 7273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return es.err; 7283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (!es.done) 7293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return EXT2_ET_EXPAND_DIR_ERR; 7303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o /* 7323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * Update the size and block count fields in the inode. 7333839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */ 7343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o retval = ext2fs_read_inode(fs, dir, &inode); 7353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o if (retval) 7363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return retval; 7373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_size += fs->blocksize; 7393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o inode.i_blocks += fs->blocksize / 512; 7403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 74108b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o e2fsck_write_inode(ctx, dir, &inode, "expand_directory"); 7423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o 7433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o return 0; 7443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o} 745