e2fsprogs/e2fsck/e2fsck.c

699 lines
18 KiB
C
Raw Normal View History

1997-04-26 17:21:57 +04:00
/*
* e2fsck.c - a consistency checker for the new extended file system.
*
* Copyright (C) 1993, 1994 Theodore Ts'o. This file may be
* redistributed under the terms of the GNU Public License.
*/
/* Usage: e2fsck [-dfpnsvy] device
* -d -- debugging this program
* -f -- check the fs even if it is marked valid
* -p -- "preen" the filesystem
* -n -- open the filesystem r/o mode; never try to fix problems
* -v -- verbose (tells how many files)
* -y -- always answer yes to questions
*
* The device may be a block device or a image of one, but this isn't
* enforced (but it's not much fun on a character device :-).
*/
#include <string.h>
#include <fcntl.h>
#include <ctype.h>
#include <termios.h>
#include <time.h>
1997-04-26 17:58:21 +04:00
#ifdef HAVE_GETOPT_H
1997-04-26 17:21:57 +04:00
#include <getopt.h>
1997-04-26 17:58:21 +04:00
#endif
1997-04-26 17:21:57 +04:00
#include <unistd.h>
1997-04-26 17:58:21 +04:00
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#ifdef HAVE_MNTENT_H
1997-04-26 17:21:57 +04:00
#include <mntent.h>
1997-04-26 17:58:21 +04:00
#endif
1997-04-26 17:21:57 +04:00
#include <sys/ioctl.h>
#include <malloc.h>
#include "et/com_err.h"
#include "e2fsck.h"
#include "../version.h"
extern int isatty(int);
const char * program_name = "e2fsck";
const char * device_name = NULL;
1997-04-26 17:58:21 +04:00
const char * filesystem_name = NULL;
1997-04-26 17:21:57 +04:00
/* Command line options */
int nflag = 0;
int yflag = 0;
int tflag = 0; /* Do timing */
int cflag = 0; /* check disk */
int preen = 0;
int rwflag = 1;
int inode_buffer_blocks = 0;
blk_t superblock;
int blocksize = 0;
int verbose = 0;
int list = 0;
int debug = 0;
int force = 0;
1997-04-26 17:34:30 +04:00
int invalid_bitmaps = 0;
1997-04-26 17:21:57 +04:00
static int show_version_only = 0;
static int replace_bad_blocks = 0;
static char *bad_blocks_file = 0;
static int possible_block_sizes[] = { 1024, 2048, 4096, 8192, 0};
struct resource_track global_rtrack;
static int root_filesystem = 0;
static int read_only_root = 0;
1997-04-26 17:34:30 +04:00
int *invalid_inode_bitmap;
int *invalid_block_bitmap;
int *invalid_inode_table;
int restart_e2fsck = 0;
1997-04-26 17:21:57 +04:00
static void usage(NOARGS)
{
fprintf(stderr,
1997-04-26 17:34:30 +04:00
"Usage: %s [-panyrcdfvtFV] [-b superblock] [-B blocksize]\n"
"\t\t[-I inode_buffer_blocks] [-P process_inode_size]\n"
"\t\t[-l|-L bad_blocks_file] device\n", program_name);
1997-04-26 17:21:57 +04:00
exit(FSCK_USAGE);
}
static void show_stats(ext2_filsys fs)
{
int inodes, inodes_used, blocks, blocks_used;
int dir_links;
int num_files, num_links;
1997-04-26 18:48:50 +04:00
int frag_percent;
1997-04-26 17:21:57 +04:00
dir_links = 2 * fs_directory_count - 1;
num_files = fs_total_count - dir_links;
num_links = fs_links_count - dir_links;
inodes = fs->super->s_inodes_count;
inodes_used = (fs->super->s_inodes_count -
fs->super->s_free_inodes_count);
blocks = fs->super->s_blocks_count;
blocks_used = (fs->super->s_blocks_count -
fs->super->s_free_blocks_count);
1997-04-26 18:48:50 +04:00
frag_percent = (10000 * fs_fragmented) / inodes_used;
frag_percent = (frag_percent + 5) / 10;
1997-04-26 17:21:57 +04:00
if (!verbose) {
1997-04-26 18:48:50 +04:00
printf("%s: %d/%d files (%0d.%d%% non-contiguous), %d/%d blocks\n",
1997-04-26 18:37:06 +04:00
device_name, inodes_used, inodes,
1997-04-26 18:48:50 +04:00
frag_percent / 10, frag_percent % 10,
1997-04-26 18:37:06 +04:00
blocks_used, blocks);
1997-04-26 17:21:57 +04:00
return;
}
1997-04-26 17:58:21 +04:00
printf ("\n%8d inode%s used (%d%%)\n", inodes_used,
1997-04-26 17:21:57 +04:00
(inodes_used != 1) ? "s" : "",
100 * inodes_used / inodes);
1997-04-26 18:48:50 +04:00
printf ("%8d non-contiguous inodes (%0d.%d%%)\n",
fs_fragmented, frag_percent / 10, frag_percent % 10);
1997-04-26 17:58:21 +04:00
printf (" # of inodes with ind/dind/tind blocks: %d/%d/%d\n",
fs_ind_count, fs_dind_count, fs_tind_count);
printf ("%8d block%s used (%d%%)\n"
"%8d bad block%s\n", blocks_used,
1997-04-26 17:21:57 +04:00
(blocks_used != 1) ? "s" : "",
100 * blocks_used / blocks, fs_badblocks_count,
fs_badblocks_count != 1 ? "s" : "");
1997-04-26 17:58:21 +04:00
printf ("\n%8d regular file%s\n"
"%8d director%s\n"
"%8d character device file%s\n"
"%8d block device file%s\n"
"%8d fifo%s\n"
"%8d link%s\n"
"%8d symbolic link%s (%d fast symbolic link%s)\n"
"%8d socket%s\n"
"--------\n"
"%8d file%s\n",
1997-04-26 17:21:57 +04:00
fs_regular_count, (fs_regular_count != 1) ? "s" : "",
fs_directory_count, (fs_directory_count != 1) ? "ies" : "y",
fs_chardev_count, (fs_chardev_count != 1) ? "s" : "",
fs_blockdev_count, (fs_blockdev_count != 1) ? "s" : "",
fs_fifo_count, (fs_fifo_count != 1) ? "s" : "",
fs_links_count - dir_links,
((fs_links_count - dir_links) != 1) ? "s" : "",
fs_symlinks_count, (fs_symlinks_count != 1) ? "s" : "",
fs_fast_symlinks_count, (fs_fast_symlinks_count != 1) ? "s" : "",
fs_sockets_count, (fs_sockets_count != 1) ? "s" : "",
fs_total_count - dir_links,
((fs_total_count - dir_links) != 1) ? "s" : "");
}
static void check_mount(NOARGS)
{
1997-04-26 17:58:21 +04:00
errcode_t retval;
1997-04-26 18:25:20 +04:00
int mount_flags, cont, fd;
1997-04-26 17:21:57 +04:00
1997-04-26 17:58:21 +04:00
retval = ext2fs_check_if_mounted(filesystem_name, &mount_flags);
if (retval) {
com_err("ext2fs_check_if_mount", retval,
"while determining whether %s is mounted.",
filesystem_name);
1997-04-26 17:21:57 +04:00
return;
1997-04-26 17:58:21 +04:00
}
if (!(mount_flags & EXT2_MF_MOUNTED))
1997-04-26 17:21:57 +04:00
return;
1997-04-26 18:25:20 +04:00
1997-04-26 18:37:06 +04:00
#if (defined(__linux__) && defined(HAVE_MNTENT_H))
1997-04-26 17:21:57 +04:00
/*
* If the root is mounted read-only, then /etc/mtab is
* probably not correct; so we won't issue a warning based on
* it.
*/
1997-04-26 18:25:20 +04:00
fd = open(MOUNTED, O_RDWR);
if (fd < 0) {
if (errno == EROFS)
return;
} else
close(fd);
#endif
1997-04-26 17:21:57 +04:00
if (!rwflag) {
printf("Warning! %s is mounted.\n", device_name);
return;
}
printf ("%s is mounted. ", device_name);
if (isatty (0) && isatty (1))
cont = ask_yn("Do you really want to continue", -1);
else
cont = 0;
if (!cont) {
printf ("check aborted.\n");
exit (0);
}
return;
}
static void sync_disks(NOARGS)
{
sync();
sync();
sleep(1);
sync();
}
1997-04-26 17:34:30 +04:00
#define MIN_CHECK 1
#define MAX_CHECK 2
static const char *corrupt_msg = "\nThe filesystem superblock is corrupt. "
"Try running e2fsck with an alternate\n"
"superblock using the -b option. "
"(8193 is commonly an alternate superblock;\n"
"Hence, 'e2fsck -b 8193 <device>' may recover the filesystem.)\n\n";
static void check_super_value(const char *descr, unsigned long value,
int flags, unsigned long min, unsigned long max)
{
if (((flags & MIN_CHECK) && (value < min)) ||
((flags & MAX_CHECK) && (value > max))) {
printf("Corruption found in superblock. (%s = %lu).\n",
descr, value);
printf(corrupt_msg);
fatal_error(0);
}
}
1997-04-26 17:21:57 +04:00
static void check_super_block(ext2_filsys fs)
{
blk_t first_block, last_block;
1997-04-26 17:34:30 +04:00
struct ext2_super_block *s = fs->super;
blk_t blocks_per_group = fs->super->s_blocks_per_group;
1997-04-26 17:21:57 +04:00
int i;
1997-04-26 17:34:30 +04:00
blk_t should_be;
1997-04-26 17:58:21 +04:00
errcode_t retval;
1997-04-26 17:21:57 +04:00
1997-04-26 17:34:30 +04:00
/*
* Verify the super block constants...
*/
check_super_value("inodes_count", s->s_inodes_count,
MIN_CHECK, 1, 0);
check_super_value("blocks_count", s->s_blocks_count,
MIN_CHECK, 1, 0);
check_super_value("first_data_block", s->s_first_data_block,
MAX_CHECK, 0, s->s_blocks_count);
check_super_value("log_frag_size", s->s_log_frag_size,
MAX_CHECK, 0, 2);
check_super_value("log_block_size", s->s_log_block_size,
MIN_CHECK | MAX_CHECK, s->s_log_frag_size,
2);
check_super_value("frags_per_group", s->s_frags_per_group,
MIN_CHECK | MAX_CHECK, 1, 8 * EXT2_BLOCK_SIZE(s));
check_super_value("blocks_per_group", s->s_blocks_per_group,
MIN_CHECK | MAX_CHECK, 1, 8 * EXT2_BLOCK_SIZE(s));
check_super_value("inodes_per_group", s->s_inodes_per_group,
MIN_CHECK, 1, 0);
check_super_value("r_blocks_count", s->s_r_blocks_count,
MAX_CHECK, 0, s->s_blocks_count);
1997-04-26 17:58:21 +04:00
retval = ext2fs_get_device_size(filesystem_name, EXT2_BLOCK_SIZE(s),
&should_be);
if (retval) {
com_err("ext2fs_get_device_size", retval,
"while trying to check physical size of filesystem");
fatal_error(0);
}
if (should_be < s->s_blocks_count) {
printf("The filesystem size (according to the superblock) is %d blocks\n", s->s_blocks_count);
printf("The physical size of the device is %d blocks\n",
should_be);
printf("Either the superblock or the partition table is likely to be corrupt!\n");
preenhalt(fs);
if (ask("Abort", 1))
fatal_error(0);
}
1997-04-26 17:34:30 +04:00
if (s->s_log_block_size != s->s_log_frag_size) {
printf("Superblock block_size = %d, fragsize = %d.\n",
EXT2_BLOCK_SIZE(s), EXT2_FRAG_SIZE(s));
printf("This version of e2fsck does not support fragment "
"sizes different\n"
"from the block size.\n");
fatal_error(0);
}
should_be = s->s_frags_per_group /
(s->s_log_block_size - s->s_log_frag_size + 1);
if (s->s_blocks_per_group != should_be) {
1997-04-26 17:58:21 +04:00
printf("Superblock blocks_per_group = %u, should "
"have been %u\n", s->s_blocks_per_group,
1997-04-26 17:34:30 +04:00
should_be);
printf(corrupt_msg);
1997-04-26 18:48:50 +04:00
fatal_error(0);
1997-04-26 17:34:30 +04:00
}
should_be = (s->s_log_block_size == 0) ? 1 : 0;
if (s->s_first_data_block != should_be) {
1997-04-26 17:58:21 +04:00
printf("Superblock first_data_block = %u, should "
"have been %u\n", s->s_first_data_block,
1997-04-26 17:34:30 +04:00
should_be);
printf(corrupt_msg);
1997-04-26 18:48:50 +04:00
fatal_error(0);
1997-04-26 17:34:30 +04:00
}
/*
* Verify the group descriptors....
*/
1997-04-26 17:21:57 +04:00
first_block = fs->super->s_first_data_block;
last_block = first_block + blocks_per_group;
for (i = 0; i < fs->group_desc_count; i++) {
1997-04-26 17:34:30 +04:00
if (i == fs->group_desc_count - 1)
last_block = fs->super->s_blocks_count;
1997-04-26 17:21:57 +04:00
if ((fs->group_desc[i].bg_block_bitmap < first_block) ||
(fs->group_desc[i].bg_block_bitmap >= last_block)) {
1997-04-26 17:58:21 +04:00
printf("Block bitmap for group %d is not in group. "
"(block %u)\n",
i, fs->group_desc[i].bg_block_bitmap);
preenhalt(fs);
if (!ask("Relocate", 1)) {
fatal_error("Block bitmap not in group");
1997-04-26 17:34:30 +04:00
}
fs->group_desc[i].bg_block_bitmap = 0;
invalid_block_bitmap[i]++;
invalid_bitmaps++;
1997-04-26 17:21:57 +04:00
}
if ((fs->group_desc[i].bg_inode_bitmap < first_block) ||
(fs->group_desc[i].bg_inode_bitmap >= last_block)) {
1997-04-26 17:58:21 +04:00
printf("Inode bitmap group %d not in group. "
"(block %u)\n",
i, fs->group_desc[i].bg_inode_bitmap);
preenhalt(fs);
if (!ask("Relocate", 1)) {
fatal_error("Inode bitmap not in group");
1997-04-26 17:34:30 +04:00
}
fs->group_desc[i].bg_inode_bitmap = 0;
invalid_inode_bitmap[i]++;
invalid_bitmaps++;
1997-04-26 17:21:57 +04:00
}
if ((fs->group_desc[i].bg_inode_table < first_block) ||
((fs->group_desc[i].bg_inode_table +
fs->inode_blocks_per_group - 1) >= last_block)) {
1997-04-26 17:58:21 +04:00
printf("Inode table for group %d not in group. "
"(block %u)\n",
i, fs->group_desc[i].bg_inode_table);
1997-04-26 17:34:30 +04:00
printf("WARNING: SEVERE DATA LOSS POSSIBLE.\n");
1997-04-26 17:58:21 +04:00
preenhalt(fs);
if (!ask("Relocate", 1)) {
fatal_error("Inode table not in group");
1997-04-26 17:34:30 +04:00
}
fs->group_desc[i].bg_inode_table = 0;
invalid_inode_table[i]++;
invalid_bitmaps++;
1997-04-26 17:21:57 +04:00
}
first_block += fs->super->s_blocks_per_group;
last_block += fs->super->s_blocks_per_group;
}
return;
}
/*
* This routine checks to see if a filesystem can be skipped; if so,
* it will exit with E2FSCK_OK. Under some conditions it will print a
* message explaining why a check is being forced.
*/
static void check_if_skip(ext2_filsys fs)
{
const char *reason = NULL;
if (force || bad_blocks_file || cflag)
return;
if (fs->super->s_state & EXT2_ERROR_FS)
reason = "contains a file system with errors";
else if (fs->super->s_mnt_count >=
(unsigned) fs->super->s_max_mnt_count)
reason = "has reached maximal mount count";
else if (fs->super->s_checkinterval &&
time(0) >= (fs->super->s_lastcheck +
fs->super->s_checkinterval))
reason = "has gone too long without being checked";
if (reason) {
printf("%s %s, check forced.\n", device_name, reason);
return;
}
if (fs->super->s_state & EXT2_VALID_FS) {
1997-04-26 17:58:21 +04:00
printf("%s: clean, %d/%d files, %d/%d blocks\n", device_name,
fs->super->s_inodes_count - fs->super->s_free_inodes_count,
fs->super->s_inodes_count,
fs->super->s_blocks_count - fs->super->s_free_blocks_count,
fs->super->s_blocks_count);
1997-04-26 17:21:57 +04:00
exit(FSCK_OK);
}
}
1997-04-26 17:58:21 +04:00
#define PATH_SET "PATH=/sbin"
1997-04-26 17:21:57 +04:00
static void PRS(int argc, char *argv[])
{
1997-04-26 17:34:30 +04:00
int flush = 0;
char c;
1997-04-26 17:21:57 +04:00
#ifdef MTRACE
1997-04-26 17:34:30 +04:00
extern void *mallwatch;
1997-04-26 17:21:57 +04:00
#endif
1997-04-26 17:58:21 +04:00
char *oldpath = getenv("PATH");
1997-04-26 17:21:57 +04:00
/* Update our PATH to include /sbin */
1997-04-26 17:58:21 +04:00
if (oldpath) {
char *newpath;
newpath = malloc(sizeof (PATH_SET) + 1 + strlen (oldpath));
if (!newpath)
fatal_error("Couldn't malloc() newpath");
strcpy (newpath, PATH_SET);
strcat (newpath, ":");
strcat (newpath, oldpath);
putenv (newpath);
} else
putenv (PATH_SET);
1997-04-26 17:21:57 +04:00
setbuf(stdout, NULL);
setbuf(stderr, NULL);
initialize_ext2_error_table();
if (argc && *argv)
program_name = *argv;
1997-04-26 17:58:21 +04:00
while ((c = getopt (argc, argv, "panyrcB:dfvtFVM:b:I:P:l:L:N:")) != EOF)
1997-04-26 17:21:57 +04:00
switch (c) {
case 'p':
case 'a':
preen = 1;
yflag = nflag = 0;
break;
case 'n':
nflag = 1;
preen = yflag = 0;
break;
case 'y':
yflag = 1;
preen = nflag = 0;
break;
case 't':
tflag++;
break;
case 'c':
cflag++;
break;
case 'r':
/* What we do by default, anyway! */
break;
case 'b':
superblock = atoi(optarg);
break;
case 'B':
blocksize = atoi(optarg);
break;
case 'I':
inode_buffer_blocks = atoi(optarg);
break;
case 'P':
process_inode_size = atoi(optarg);
break;
case 'L':
replace_bad_blocks++;
case 'l':
bad_blocks_file = malloc(strlen(optarg)+1);
if (!bad_blocks_file)
fatal_error("Couldn't malloc bad_blocks_file");
strcpy(bad_blocks_file, optarg);
break;
case 'd':
debug = 1;
break;
case 'f':
force = 1;
break;
case 'F':
1997-04-26 17:58:21 +04:00
#ifdef BLKFLSBUF
1997-04-26 17:21:57 +04:00
flush = 1;
1997-04-26 17:58:21 +04:00
#else
fatal_error ("-F not supported");
#endif
1997-04-26 17:21:57 +04:00
break;
case 'v':
verbose = 1;
break;
case 'V':
show_version_only = 1;
break;
#ifdef MTRACE
case 'M':
mallwatch = (void *) strtol(optarg, NULL, 0);
break;
#endif
1997-04-26 17:58:21 +04:00
case 'N':
device_name = optarg;
break;
1997-04-26 17:21:57 +04:00
default:
usage ();
}
if (show_version_only)
return;
if (optind != argc - 1)
usage ();
if (nflag && !bad_blocks_file && !cflag)
rwflag = 0;
1997-04-26 17:58:21 +04:00
filesystem_name = argv[optind];
if (device_name == 0)
device_name = filesystem_name;
1997-04-26 17:21:57 +04:00
if (flush) {
1997-04-26 17:58:21 +04:00
#ifdef BLKFLSBUF
int fd = open(filesystem_name, O_RDONLY, 0);
1997-04-26 17:21:57 +04:00
if (fd < 0) {
com_err("open", errno, "while opening %s for flushing",
1997-04-26 17:58:21 +04:00
filesystem_name);
1997-04-26 17:21:57 +04:00
exit(FSCK_ERROR);
}
if (ioctl(fd, BLKFLSBUF, 0) < 0) {
com_err("BLKFLSBUF", errno, "while trying to flush %s",
1997-04-26 17:58:21 +04:00
filesystem_name);
1997-04-26 17:21:57 +04:00
exit(FSCK_ERROR);
}
close(fd);
1997-04-26 17:58:21 +04:00
#else
fatal_error ("BLKFLSBUF not supported");
#endif /* BLKFLSBUF */
1997-04-26 17:21:57 +04:00
}
}
int main (int argc, char *argv[])
{
errcode_t retval = 0;
int exit_value = FSCK_OK;
int i;
ext2_filsys fs;
#ifdef MTRACE
mtrace();
#endif
#ifdef MCHECK
mcheck(0);
#endif
init_resource_track(&global_rtrack);
PRS(argc, argv);
if (!preen)
fprintf (stderr, "e2fsck %s, %s for EXT2 FS %s, %s\n",
E2FSPROGS_VERSION, E2FSPROGS_DATE,
EXT2FS_VERSION, EXT2FS_DATE);
if (show_version_only)
exit(0);
check_mount();
if (!preen && !nflag && !yflag) {
if (!isatty (0) || !isatty (1))
die ("need terminal for interactive repairs");
}
1997-04-26 17:34:30 +04:00
restart:
1997-04-26 17:21:57 +04:00
sync_disks();
if (superblock && blocksize) {
1997-04-26 17:58:21 +04:00
retval = ext2fs_open(filesystem_name,
rwflag ? EXT2_FLAG_RW : 0,
1997-04-26 17:21:57 +04:00
superblock, blocksize, unix_io_manager,
&fs);
} else if (superblock) {
for (i=0; possible_block_sizes[i]; i++) {
1997-04-26 17:58:21 +04:00
retval = ext2fs_open(filesystem_name,
1997-04-26 17:21:57 +04:00
rwflag ? EXT2_FLAG_RW : 0,
superblock,
possible_block_sizes[i],
unix_io_manager, &fs);
if (!retval)
break;
}
} else
1997-04-26 17:58:21 +04:00
retval = ext2fs_open(filesystem_name,
rwflag ? EXT2_FLAG_RW : 0,
1997-04-26 17:21:57 +04:00
0, 0, unix_io_manager, &fs);
if (retval) {
com_err(program_name, retval, "while trying to open %s",
1997-04-26 17:58:21 +04:00
filesystem_name);
switch (retval) {
case EXT2_ET_REV_TOO_HIGH:
1997-04-26 17:34:30 +04:00
printf ("Get a newer version of e2fsck!\n");
1997-04-26 17:58:21 +04:00
break;
case EXT2_ET_SHORT_READ:
printf ("Could this be a zero-length partition?\n");
break;
case EPERM:
case EACCES:
printf("You must have %s access to the "
"filesystem or be root\n",
rwflag ? "r/w" : "r/o");
break;
case ENXIO:
printf("Possibly non-existent or swap device?\n");
break;
default:
1997-04-26 17:34:30 +04:00
printf(corrupt_msg);
1997-04-26 17:58:21 +04:00
}
1997-04-26 17:21:57 +04:00
fatal_error(0);
}
1997-04-26 17:34:30 +04:00
#ifdef EXT2_CURRENT_REV
if (fs->super->s_rev_level > E2FSCK_CURRENT_REV) {
1997-04-26 18:48:50 +04:00
com_err(program_name, EXT2_ET_REV_TOO_HIGH,
"while trying to open %s",
1997-04-26 17:58:21 +04:00
filesystem_name);
1997-04-26 17:34:30 +04:00
printf ("Get a newer version of e2fsck!\n");
fatal_error(0);
}
#endif
1997-04-26 17:21:57 +04:00
/*
* If the user specified a specific superblock, presumably the
* master superblock has been trashed. So we mark the
* superblock as dirty, so it can be written out.
*/
if (superblock && rwflag)
ext2fs_mark_super_dirty(fs);
ehandler_init(fs->io);
1997-04-26 17:34:30 +04:00
invalid_inode_bitmap = allocate_memory(sizeof(int) *
fs->group_desc_count,
"invalid_inode_bitmap");
invalid_block_bitmap = allocate_memory(sizeof(int) *
fs->group_desc_count,
"invalid_block_bitmap");
invalid_inode_table = allocate_memory(sizeof(int) *
fs->group_desc_count,
"invalid_inode_table");
1997-04-26 17:21:57 +04:00
check_super_block(fs);
check_if_skip(fs);
if (bad_blocks_file)
read_bad_blocks_file(fs, bad_blocks_file, replace_bad_blocks);
else if (cflag)
test_disk(fs);
/*
* Mark the system as valid, 'til proven otherwise
*/
ext2fs_mark_valid(fs);
pass1(fs);
1997-04-26 17:58:21 +04:00
free(invalid_inode_bitmap);
free(invalid_block_bitmap);
free(invalid_inode_table);
1997-04-26 17:34:30 +04:00
if (restart_e2fsck) {
ext2fs_close(fs);
printf("Restarting e2fsck from the beginning...\n");
restart_e2fsck = 0;
goto restart;
}
1997-04-26 17:21:57 +04:00
pass2(fs);
pass3(fs);
pass4(fs);
pass5(fs);
#ifdef MTRACE
mtrace_print("Cleanup");
#endif
if (ext2fs_test_changed(fs)) {
exit_value = FSCK_NONDESTRUCT;
if (!preen)
printf("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n",
device_name);
if (root_filesystem && !read_only_root) {
printf("%s: ***** REBOOT LINUX *****\n", device_name);
exit_value = FSCK_REBOOT;
}
}
if (!ext2fs_test_valid(fs))
exit_value = FSCK_UNCORRECTED;
if (rwflag) {
if (ext2fs_test_valid(fs))
fs->super->s_state = EXT2_VALID_FS;
else
fs->super->s_state &= ~EXT2_VALID_FS;
fs->super->s_mnt_count = 0;
fs->super->s_lastcheck = time(NULL);
ext2fs_mark_super_dirty(fs);
}
show_stats(fs);
write_bitmaps(fs);
ext2fs_close(fs);
sync_disks();
if (tflag)
print_resource_track(&global_rtrack);
return exit_value;
}