📄 e2fsck.c
字号:
/* * Need a full fsck if we are releasing a * journal stored on a reserved inode. */ force_fsck = recover || (sb->s_journal_inum < EXT2_FIRST_INODE(sb)); /* Clear all of the journal fields */ sb->s_journal_inum = 0; sb->s_journal_dev = 0; memset(sb->s_journal_uuid, 0, sizeof(sb->s_journal_uuid)); e2fsck_clear_recover(ctx, force_fsck); } else if (!(ctx->options & E2F_OPT_READONLY)) { sb->s_feature_compat |= EXT3_FEATURE_COMPAT_HAS_JOURNAL; ext2fs_mark_super_dirty(ctx->fs); } } if (sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL && !(sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) && journal->j_superblock->s_start != 0) { /* Print status information */ fix_problem(ctx, PR_0_JOURNAL_RECOVERY_CLEAR, &pctx); if (ctx->superblock) problem = PR_0_JOURNAL_RUN_DEFAULT; else problem = PR_0_JOURNAL_RUN; if (fix_problem(ctx, problem, &pctx)) { ctx->options |= E2F_OPT_FORCE; sb->s_feature_incompat |= EXT3_FEATURE_INCOMPAT_RECOVER; ext2fs_mark_super_dirty(ctx->fs); } else if (fix_problem(ctx, PR_0_JOURNAL_RESET_JOURNAL, &pctx)) { reset = 1; sb->s_state &= ~EXT2_VALID_FS; ext2fs_mark_super_dirty(ctx->fs); } /* * If the user answers no to the above question, we * ignore the fact that journal apparently has data; * accidentally replaying over valid data would be far * worse than skipping a questionable recovery. * * XXX should we abort with a fatal error here? What * will the ext3 kernel code do if a filesystem with * !NEEDS_RECOVERY but with a non-zero * journal->j_superblock->s_start is mounted? */ } e2fsck_journal_release(ctx, journal, reset, 0); return retval;}static errcode_t recover_ext3_journal(e2fsck_t ctx){ journal_t *journal; int retval; journal_init_revoke_caches(); retval = e2fsck_get_journal(ctx, &journal); if (retval) return retval; retval = e2fsck_journal_load(journal); if (retval) goto errout; retval = journal_init_revoke(journal, 1024); if (retval) goto errout; retval = -journal_recover(journal); if (retval) goto errout; if (journal->j_superblock->s_errno) { ctx->fs->super->s_state |= EXT2_ERROR_FS; ext2fs_mark_super_dirty(ctx->fs); journal->j_superblock->s_errno = 0; mark_buffer_dirty(journal->j_sb_buffer); }errout: journal_destroy_revoke(journal); journal_destroy_revoke_caches(); e2fsck_journal_release(ctx, journal, 1, 0); return retval;}static int e2fsck_run_ext3_journal(e2fsck_t ctx){ io_manager io_ptr = ctx->fs->io->manager; int blocksize = ctx->fs->blocksize; errcode_t retval, recover_retval; printf(_("%s: recovering journal\n"), ctx->device_name); if (ctx->options & E2F_OPT_READONLY) { printf(_("%s: won't do journal recovery while read-only\n"), ctx->device_name); return EXT2_ET_FILE_RO; } if (ctx->fs->flags & EXT2_FLAG_DIRTY) ext2fs_flush(ctx->fs); /* Force out any modifications */ recover_retval = recover_ext3_journal(ctx); /* * Reload the filesystem context to get up-to-date data from disk * because journal recovery will change the filesystem under us. */ ext2fs_close(ctx->fs); retval = ext2fs_open(ctx->filesystem_name, EXT2_FLAG_RW, ctx->superblock, blocksize, io_ptr, &ctx->fs); if (retval) { bb_error_msg(_("while trying to re-open %s"), ctx->device_name); bb_error_msg_and_die(0); } ctx->fs->priv_data = ctx; /* Set the superblock flags */ e2fsck_clear_recover(ctx, recover_retval); return recover_retval;}/* * This function will move the journal inode from a visible file in * the filesystem directory hierarchy to the reserved inode if necessary. */static const char *const journal_names[] = { ".journal", "journal", ".journal.dat", "journal.dat", 0 };static void e2fsck_move_ext3_journal(e2fsck_t ctx){ struct ext2_super_block *sb = ctx->fs->super; struct problem_context pctx; struct ext2_inode inode; ext2_filsys fs = ctx->fs; ext2_ino_t ino; errcode_t retval; const char *const * cpp; int group, mount_flags; clear_problem_context(&pctx); /* * If the filesystem is opened read-only, or there is no * journal, then do nothing. */ if ((ctx->options & E2F_OPT_READONLY) || (sb->s_journal_inum == 0) || !(sb->s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL)) return; /* * Read in the journal inode */ if (ext2fs_read_inode(fs, sb->s_journal_inum, &inode) != 0) return; /* * If it's necessary to backup the journal inode, do so. */ if ((sb->s_jnl_backup_type == 0) || ((sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS) && memcmp(inode.i_block, sb->s_jnl_blocks, EXT2_N_BLOCKS*4))) { if (fix_problem(ctx, PR_0_BACKUP_JNL, &pctx)) { memcpy(sb->s_jnl_blocks, inode.i_block, EXT2_N_BLOCKS*4); sb->s_jnl_blocks[16] = inode.i_size; sb->s_jnl_backup_type = EXT3_JNL_BACKUP_BLOCKS; ext2fs_mark_super_dirty(fs); fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; } } /* * If the journal is already the hidden inode, then do nothing */ if (sb->s_journal_inum == EXT2_JOURNAL_INO) return; /* * The journal inode had better have only one link and not be readable. */ if (inode.i_links_count != 1) return; /* * If the filesystem is mounted, or we can't tell whether * or not it's mounted, do nothing. */ retval = ext2fs_check_if_mounted(ctx->filesystem_name, &mount_flags); if (retval || (mount_flags & EXT2_MF_MOUNTED)) return; /* * If we can't find the name of the journal inode, then do * nothing. */ for (cpp = journal_names; *cpp; cpp++) { retval = ext2fs_lookup(fs, EXT2_ROOT_INO, *cpp, strlen(*cpp), 0, &ino); if ((retval == 0) && (ino == sb->s_journal_inum)) break; } if (*cpp == 0) return; /* We need the inode bitmap to be loaded */ retval = ext2fs_read_bitmaps(fs); if (retval) return; pctx.str = *cpp; if (!fix_problem(ctx, PR_0_MOVE_JOURNAL, &pctx)) return; /* * OK, we've done all the checks, let's actually move the * journal inode. Errors at this point mean we need to force * an ext2 filesystem check. */ if ((retval = ext2fs_unlink(fs, EXT2_ROOT_INO, *cpp, ino, 0)) != 0) goto err_out; if ((retval = ext2fs_write_inode(fs, EXT2_JOURNAL_INO, &inode)) != 0) goto err_out; sb->s_journal_inum = EXT2_JOURNAL_INO; ext2fs_mark_super_dirty(fs); fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY; inode.i_links_count = 0; inode.i_dtime = time(0); if ((retval = ext2fs_write_inode(fs, ino, &inode)) != 0) goto err_out; group = ext2fs_group_of_ino(fs, ino); ext2fs_unmark_inode_bitmap(fs->inode_map, ino); ext2fs_mark_ib_dirty(fs); fs->group_desc[group].bg_free_inodes_count++; fs->super->s_free_inodes_count++; return;err_out: pctx.errcode = retval; fix_problem(ctx, PR_0_ERR_MOVE_JOURNAL, &pctx); fs->super->s_state &= ~EXT2_VALID_FS; ext2fs_mark_super_dirty(fs);}/* * message.c --- print e2fsck messages (with compression) * * print_e2fsck_message() prints a message to the user, using * compression techniques and expansions of abbreviations. * * The following % expansions are supported: * * %b <blk> block number * %B <blkcount> integer * %c <blk2> block number * %Di <dirent>->ino inode number * %Dn <dirent>->name string * %Dr <dirent>->rec_len * %Dl <dirent>->name_len * %Dt <dirent>->filetype * %d <dir> inode number * %g <group> integer * %i <ino> inode number * %Is <inode> -> i_size * %IS <inode> -> i_extra_isize * %Ib <inode> -> i_blocks * %Il <inode> -> i_links_count * %Im <inode> -> i_mode * %IM <inode> -> i_mtime * %IF <inode> -> i_faddr * %If <inode> -> i_file_acl * %Id <inode> -> i_dir_acl * %Iu <inode> -> i_uid * %Ig <inode> -> i_gid * %j <ino2> inode number * %m <com_err error message> * %N <num> * %p ext2fs_get_pathname of directory <ino> * %P ext2fs_get_pathname of <dirent>->ino with <ino2> as * the containing directory. (If dirent is NULL * then return the pathname of directory <ino2>) * %q ext2fs_get_pathname of directory <dir> * %Q ext2fs_get_pathname of directory <ino> with <dir> as * the containing directory. * %s <str> miscellaneous string * %S backup superblock * %X <num> hexadecimal format * * The following '@' expansions are supported: * * @a extended attribute * @A error allocating * @b block * @B bitmap * @c compress * @C conflicts with some other fs block * @D deleted * @d directory * @e entry * @E Entry '%Dn' in %p (%i) * @f filesystem * @F for @i %i (%Q) is * @g group * @h HTREE directory inode * @i inode * @I illegal * @j journal * @l lost+found * @L is a link * @m multiply-claimed * @n invalid * @o orphaned * @p problem in * @r root inode * @s should be * @S superblock * @u unattached * @v device * @z zero-length *//* * This structure defines the abbreviations used by the text strings * below. The first character in the string is the index letter. An * abbreviation of the form '@<i>' is expanded by looking up the index * letter <i> in the table below. */static const char *const abbrevs[] = { N_("aextended attribute"), N_("Aerror allocating"), N_("bblock"), N_("Bbitmap"), N_("ccompress"), N_("Cconflicts with some other fs @b"), N_("iinode"), N_("Iillegal"), N_("jjournal"), N_("Ddeleted"), N_("ddirectory"), N_("eentry"), N_("E@e '%Dn' in %p (%i)"), N_("ffilesystem"), N_("Ffor @i %i (%Q) is"), N_("ggroup"), N_("hHTREE @d @i"), N_("llost+found"), N_("Lis a link"), N_("mmultiply-claimed"), N_("ninvalid"), N_("oorphaned"), N_("pproblem in"), N_("rroot @i"), N_("sshould be"), N_("Ssuper@b"), N_("uunattached"), N_("vdevice"), N_("zzero-length"), "@@", 0 };/* * Give more user friendly names to the "special" inodes. */#define num_special_inodes 11static const char *const special_inode_name[] ={ N_("<The NULL inode>"), /* 0 */ N_("<The bad blocks inode>"), /* 1 */ "/", /* 2 */ N_("<The ACL index inode>"), /* 3 */ N_("<The ACL data inode>"), /* 4 */ N_("<The boot loader inode>"), /* 5 */ N_("<The undelete directory inode>"), /* 6 */ N_("<The group descriptor inode>"), /* 7 */ N_("<The journal inode>"), /* 8 */ N_("<Reserved inode 9>"), /* 9 */ N_("<Reserved inode 10>"), /* 10 */};/* * This function does "safe" printing. It will convert non-printable * ASCII characters using '^' and M- notation. */static void safe_print(const char *cp, int len){ unsigned char ch; if (len < 0) len = strlen(cp); while (len--) { ch = *cp++; if (ch > 128) { fputs("M-", stdout); ch -= 128; } if ((ch < 32) || (ch == 0x7f)) { fputc('^', stdout); ch ^= 0x40; /* ^@, ^A, ^B; ^? for DEL */ } fputc(ch, stdout); }}/* * This function prints a pathname, using the ext2fs_get_pathname * function */static void print_pathname(ext2_filsys fs, ext2_ino_t dir, ext2_ino_t ino){ errcode_t retval; char *path; if (!dir && (ino < num_special_inodes)) { fputs(_(special_inode_name[ino]), stdout); return; } retval = ext2fs_get_pathname(fs, dir, ino, &path); if (retval) fputs("???", stdout); else { safe_print(path, -1); ext2fs_free_mem(&path); }}static void print_e2fsck_message(e2fsck_t ctx, const char *msg, struct problem_context *pctx, int first);/* * This function handles the '@' expansion. We allow recursive * expansion; an @ expression can contain further '@' and '%' * expressions. */static void expand_at_expression(e2fsck_t ctx, char ch, struct problem_context *pctx, int *first){ const char *const *cpp; const char *str; /* Search for the abbreviation */ for (cpp = abbrevs; *cpp; cpp++) { if (ch == *cpp[0]) break; } if (*cpp) { str = _(*cpp) + 1; if (*first && islower(*str)) { *first = 0; fputc(toupper(*str++), stdout); } print_e2fsck_message(ctx, str, pctx, *first); } else printf("@%c", ch);}/* * This function expands '%IX' expressions */static void expand_inode_expression(char ch, struct problem_context *ctx){ struct ext2_inode *inode; struct ext2_inode_large *large_inode; char * time_str; time_t t; int do_gmt = -1; if (!ctx || !ctx->inode) goto no_inode; inode = ctx->inode; large_inode = (struct ext2_inode_large *) inode; switch (ch) { case 's': if (LINUX_S_ISDIR(inode->i_mode)) printf("%u", inode->i_size); else { printf("%"PRIu64, (inode->i_size | ((uint64_t) inode->i_size_high << 32))); } break; case 'S': printf("%u", large_inode->i_extra_isize); break; case 'b': printf("%u", inode->i_blocks); break; case 'l': printf("%d", inode->i_links_count); break; case 'm': pr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -