unix.c revision c0a849660d1aea86b9f3ff986aae7b705a059e3e
1eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/*
2eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * unix.c - The unix-specific code for e2fsck
3eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *
4eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
5eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch *
6f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * %Begin-Header%
7a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * This file may be redistributed under the terms of the GNU Public
8424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles) * License.
9f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) * %End-Header%
10eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch */
11eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
12424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#define _XOPEN_SOURCE 600 /* for inclusion of sa_handler in Solaris */
131320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include "config.h"
155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <stdio.h>
165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifdef HAVE_STDLIB_H
17424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include <stdlib.h>
18424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#endif
19424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include <string.h>
20424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include <fcntl.h>
211320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include <ctype.h>
225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <time.h>
235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifdef HAVE_SIGNAL_H
245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#include <signal.h>
254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifdef HAVE_GETOPT_H
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <getopt.h>
284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#else
294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)extern char *optarg;
304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)extern int optind;
314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif
324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <unistd.h>
334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifdef HAVE_ERRNO_H
344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <errno.h>
354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif
364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifdef HAVE_SYS_IOCTL_H
374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <sys/ioctl.h>
384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifdef HAVE_MALLOC_H
404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <malloc.h>
414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif
424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifdef HAVE_SYS_TYPES_H
434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <sys/types.h>
444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif
454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#ifdef HAVE_DIRENT_H
464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include <dirent.h>
474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#endif
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
49424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "e2p/e2p.h"
50424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)#include "et/com_err.h"
51eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "e2p/e2p.h"
52a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "e2fsck.h"
53eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#include "problem.h"
54558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "../version.h"
55558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch
56558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch/* Command line options */
57558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochstatic int cflag;		/* check disk */
58f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static int show_version_only;
59f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static int verbose;
60eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
61eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int replace_bad_blocks;
62eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int keep_bad_blocks;
63f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)static char *bad_blocks_file;
64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)e2fsck_t e2fsck_global_ctx;	/* Try your very best not to use this! */
66f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
67eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#ifdef CONFIG_JBD_DEBUG		/* Enabled by configure --enable-jfs-debug */
68f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)int journal_enable_debug = -1;
69f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#endif
70eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
71eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic void usage(e2fsck_t ctx)
72eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{
731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	fprintf(stderr,
741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci		_("Usage: %s [-panyrcdfvtDFV] [-b superblock] [-B blocksize]\n"
75424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		"\t\t[-I inode_buffer_blocks] [-P process_inode_size]\n"
76424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		"\t\t[-l|-L bad_blocks_file] [-C fd] [-j external_journal]\n"
77424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		"\t\t[-E extended-options] device\n"),
78424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		ctx->program_name);
79424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
80424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)	fprintf(stderr, _("\nEmergency help:\n"
81424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		" -p                   Automatic repair (no questions)\n"
82424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		" -n                   Make no changes to the filesystem\n"
83424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		" -y                   Assume \"yes\" to all questions\n"
84424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		" -c                   Check for bad blocks and add them to the badblock list\n"
85424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		" -f                   Force checking even if filesystem is marked clean\n"));
86424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)	fprintf(stderr, _(""
87eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		" -v                   Be verbose\n"
88eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		" -b superblock        Use alternative superblock\n"
89eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		" -B blocksize         Force blocksize when looking for superblock\n"
90eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		" -j external_journal  Set location of the external journal\n"
91558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch		" -l bad_blocks_file   Add to badblocks list\n"
92558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch		" -L bad_blocks_file   Set badblocks list\n"
93eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		));
94eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
95ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch	exit(FSCK_USAGE);
96eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
97eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
98ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochstatic void show_stats(e2fsck_t	ctx)
99eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{
100ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch	ext2_filsys fs = ctx->fs;
101ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch	ext2_ino_t inodes, inodes_used;
102eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	blk64_t blocks, blocks_used;
103eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	unsigned int dir_links;
104eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	unsigned int num_files, num_links;
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	__u32 *mask, m;
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	int frag_percent_file, frag_percent_dir, frag_percent_total;
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	int i, j, printed = 0;
108ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch
109ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch	dir_links = 2 * ctx->fs_directory_count - 1;
110ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch	num_files = ctx->fs_total_count - dir_links;
1111320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	num_links = ctx->fs_links_count - dir_links;
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	inodes = fs->super->s_inodes_count;
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	inodes_used = (fs->super->s_inodes_count -
114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		       fs->super->s_free_inodes_count);
115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	blocks = ext2fs_blocks_count(fs->super);
116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	blocks_used = (ext2fs_blocks_count(fs->super) -
117f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		       ext2fs_free_blocks_count(fs->super));
118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
119424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)	frag_percent_file = (10000 * ctx->fs_fragmented) / inodes_used;
1205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	frag_percent_file = (frag_percent_file + 5) / 10;
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	frag_percent_dir = (10000 * ctx->fs_fragmented_dir) / inodes_used;
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	frag_percent_dir = (frag_percent_dir + 5) / 10;
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	frag_percent_total = ((10000 * (ctx->fs_fragmented +
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)					ctx->fs_fragmented_dir))
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			      / inodes_used);
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	frag_percent_total = (frag_percent_total + 5) / 10;
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if (!verbose) {
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		log_out(ctx, _("%s: %u/%u files (%0d.%d%% non-contiguous), "
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			       "%llu/%llu blocks\n"),
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			ctx->device_name, inodes_used, inodes,
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			frag_percent_total / 10, frag_percent_total % 10,
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			blocks_used, blocks);
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		return;
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	}
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	profile_get_boolean(ctx->profile, "options", "report_features", 0, 0,
139a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)			    &i);
1401320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	if (verbose && i) {
141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		log_out(ctx, "\nFilesystem features:");
142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		mask = &ctx->fs->super->s_feature_compat;
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		for (i = 0; i < 3; i++, mask++) {
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			for (j = 0, m = 1; j < 32; j++, m <<= 1) {
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)				if (*mask & m) {
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)					log_out(ctx, " %s",
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)						e2p_feature2string(i, m));
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)					printed++;
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)				}
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			}
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		}
152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (printed == 0)
153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			log_out(ctx, " (none)");
154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		log_out(ctx, "\n");
155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	log_out(ctx, P_("\n%8u inode used (%2.2f%%)\n",
158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			"\n%8u inodes used (%2.2f%%)\n",
159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			inodes_used), inodes_used,
160424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		100.0 * inodes_used / inodes);
161116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch	log_out(ctx, P_("%8u non-contiguous file (%0d.%d%%)\n",
162116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch			"%8u non-contiguous files (%0d.%d%%)\n",
163116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch			ctx->fs_fragmented),
164424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		ctx->fs_fragmented, frag_percent_file / 10,
165424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		frag_percent_file % 10);
166424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)	log_out(ctx, P_("%8u non-contiguous directory (%0d.%d%%)\n",
167424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)			"%8u non-contiguous directories (%0d.%d%%)\n",
168424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)			ctx->fs_fragmented_dir),
169eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		ctx->fs_fragmented_dir, frag_percent_dir / 10,
170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		frag_percent_dir % 10);
171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	log_out(ctx, _("         # of inodes with ind/dind/tind blocks: "
172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		       "%u/%u/%u\n"),
173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		ctx->fs_ind_count, ctx->fs_dind_count, ctx->fs_tind_count);
174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
175424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)	for (j=MAX_EXTENT_DEPTH_COUNT-1; j >=0; j--)
176424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		if (ctx->extent_depth_count[j])
177424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)			break;
178424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)	if (++j) {
179424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		log_out(ctx, _("         Extent depth histogram: "));
180424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		for (i=0; i < j; i++) {
181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			if (i)
182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				fputc('/', stdout);
183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			log_out(ctx, "%u", ctx->extent_depth_count[i]);
184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		}
185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		log_out(ctx, "\n");
186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	log_out(ctx, P_("%8llu block used (%2.2f%%)\n",
189424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)			"%8llu blocks used (%2.2f%%)\n",
190424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		   blocks_used), blocks_used, 100.0 * blocks_used / blocks);
191424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)	log_out(ctx, P_("%8u bad block\n", "%8u bad blocks\n",
192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			ctx->fs_badblocks_count), ctx->fs_badblocks_count);
193eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	log_out(ctx, P_("%8u large file\n", "%8u large files\n",
194eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			ctx->large_files), ctx->large_files);
195eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	log_out(ctx, P_("\n%8u regular file\n", "\n%8u regular files\n",
196eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			ctx->fs_regular_count), ctx->fs_regular_count);
197eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	log_out(ctx, P_("%8u directory\n", "%8u directories\n",
198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			ctx->fs_directory_count), ctx->fs_directory_count);
199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	log_out(ctx, P_("%8u character device file\n",
200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			"%8u character device files\n", ctx->fs_chardev_count),
201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		ctx->fs_chardev_count);
202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	log_out(ctx, P_("%8u block device file\n", "%8u block device files\n",
203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			ctx->fs_blockdev_count), ctx->fs_blockdev_count);
204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	log_out(ctx, P_("%8u fifo\n", "%8u fifos\n", ctx->fs_fifo_count),
205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		ctx->fs_fifo_count);
206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	log_out(ctx, P_("%8u link\n", "%8u links\n",
207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			ctx->fs_links_count - dir_links),
2081320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci		ctx->fs_links_count - dir_links);
209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	log_out(ctx, P_("%8u symbolic link", "%8u symbolic links",
210ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch			ctx->fs_symlinks_count), ctx->fs_symlinks_count);
2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	log_out(ctx, P_(" (%u fast symbolic link)\n",
2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			" (%u fast symbolic links)\n",
2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			ctx->fs_fast_symlinks_count),
2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		ctx->fs_fast_symlinks_count);
215effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch	log_out(ctx, P_("%8u socket\n", "%8u sockets\n", ctx->fs_sockets_count),
216effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch		ctx->fs_sockets_count);
2175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	log_out(ctx, "--------\n");
218ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch	log_out(ctx, P_("%8u file\n", "%8u files\n",
219eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			ctx->fs_total_count - dir_links),
220eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		ctx->fs_total_count - dir_links);
221eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
222424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
223424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)static void check_mount(e2fsck_t ctx)
224424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles){
2251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	errcode_t	retval;
2261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	int		cont;
227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
228eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	retval = ext2fs_check_if_mounted(ctx->filesystem_name,
2295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)					 &ctx->mount_flags);
2305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if (retval) {
2315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		com_err("ext2fs_check_if_mount", retval,
2325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			_("while determining whether %s is mounted."),
2335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			ctx->filesystem_name);
2345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		return;
2355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	}
2365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
2375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	/*
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 * If the filesystem isn't mounted, or it's the root
2395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 * filesystem and it's mounted read-only, and we're not doing
2405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 * a read/write check, then everything's fine.
241f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	 */
242f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	if ((!(ctx->mount_flags & (EXT2_MF_MOUNTED | EXT2_MF_BUSY))) ||
243f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	    ((ctx->mount_flags & EXT2_MF_ISROOT) &&
244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	     (ctx->mount_flags & EXT2_MF_READONLY) &&
245f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	     !(ctx->options & E2F_OPT_WRITECHECK)))
246f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		return;
247f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	if (((ctx->options & E2F_OPT_READONLY) ||
249f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	     ((ctx->options & E2F_OPT_FORCE) &&
250f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	      (ctx->mount_flags & EXT2_MF_READONLY))) &&
251f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	    !(ctx->options & E2F_OPT_WRITECHECK)) {
252f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		log_out(ctx, _("Warning!  %s is %s.\n"),
253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)			ctx->filesystem_name,
254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)			ctx->mount_flags & EXT2_MF_MOUNTED ?
255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)				"mounted" : "in use");
256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		return;
257f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	}
258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	log_out(ctx, _("%s is %s.\n"), ctx->filesystem_name,
260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		ctx->mount_flags & EXT2_MF_MOUNTED ? "mounted" : "in use");
261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	if (!ctx->interactive || ctx->mount_flags & EXT2_MF_BUSY)
262f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		fatal_error(ctx, _("Cannot continue, aborting.\n\n"));
263116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch	puts("\007\007\007\007");
264116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch	log_out(ctx, _("\n\nWARNING!!!  "
265116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch		       "The filesystem is mounted.   "
266116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch		       "If you continue you ***WILL***\n"
267116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch		       "cause ***SEVERE*** filesystem damage.\n\n"));
268116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch	puts("\007\007\007");
269116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch	cont = ask_yn(ctx, _("Do you really want to continue"), 0);
270116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch	if (!cont) {
271f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		printf (_("check aborted.\n"));
272f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		exit (0);
273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	return;
275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int is_on_batt(void)
2781320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci{
2791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	FILE	*f;
280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	DIR	*d;
281f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	char	tmp[80], tmp2[80], fname[80];
282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	unsigned int	acflag;
283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	struct dirent*	de;
284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)
285f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	f = fopen("/sys/class/power_supply/AC/online", "r");
286f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	if (f) {
287f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)		if (fscanf(f, "%u\n", &acflag) == 1) {
288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)			fclose(f);
289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)			return (!acflag);
290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		}
291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		fclose(f);
292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	f = fopen("/proc/apm", "r");
294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (f) {
295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (fscanf(f, "%s %s %s %x", tmp, tmp, tmp, &acflag) != 4)
296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			acflag = 1;
297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		fclose(f);
2985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		return (acflag != 1);
2995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	}
3005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	d = opendir("/proc/acpi/ac_adapter");
3015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if (d) {
3025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		while ((de=readdir(d)) != NULL) {
3035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			if (!strncmp(".", de->d_name, 1))
3045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)				continue;
3055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			snprintf(fname, 80, "/proc/acpi/ac_adapter/%s/state",
3065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)				 de->d_name);
3075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			f = fopen(fname, "r");
3085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			if (!f)
3095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)				continue;
3105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			if (fscanf(f, "%s %s", tmp2, tmp) != 2)
3115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)				tmp[0] = 0;
3125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			fclose(f);
3135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			if (strncmp(tmp, "off-line", 8) == 0) {
314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				closedir(d);
315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				return 1;
316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			}
317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		}
3185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		closedir(d);
319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	return 0;
3215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
3225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
3235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/*
3245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * This routine checks to see if a filesystem can be skipped; if so,
3255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * it will exit with E2FSCK_OK.  Under some conditions it will print a
3265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * message explaining why a check is being forced.
3275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */
3285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static void check_if_skip(e2fsck_t ctx)
3295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles){
330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	ext2_filsys fs = ctx->fs;
3311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	struct problem_context pctx;
332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	const char *reason = NULL;
333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	unsigned int reason_arg = 0;
334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	long next_check;
335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	int batt = is_on_batt();
336424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)	int defer_check_on_battery;
337424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)	int broken_system_clock;
338424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)	time_t lastcheck;
339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	profile_get_boolean(ctx->profile, "options", "broken_system_clock",
341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			    0, 0, &broken_system_clock);
342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (ctx->flags & E2F_FLAG_TIME_INSANE)
343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		broken_system_clock = 1;
344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	profile_get_boolean(ctx->profile, "options",
3451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci			    "defer_check_on_battery", 0, 1,
346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			    &defer_check_on_battery);
347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (!defer_check_on_battery)
348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		batt = 0;
349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
350424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)	if ((ctx->options & E2F_OPT_FORCE) || bad_blocks_file || cflag)
351424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		return;
352424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)
353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (ctx->options & E2F_OPT_JOURNAL_ONLY)
354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		goto skip;
355eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	lastcheck = fs->super->s_lastcheck;
357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (lastcheck > ctx->now)
358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		lastcheck -= ctx->time_fudge;
359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if ((fs->super->s_state & EXT2_ERROR_FS) ||
3601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	    !ext2fs_test_valid(fs))
361424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		reason = _(" contains a file system with errors");
362424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)	else if ((fs->super->s_state & EXT2_VALID_FS) == 0)
363424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		reason = _(" was not cleanly unmounted");
364424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)	else if (check_backup_super_block(ctx))
365424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		reason = _(" primary superblock features different from backup");
366424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)	else if ((fs->super->s_max_mnt_count > 0) &&
367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		 (fs->super->s_mnt_count >=
368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		  (unsigned) fs->super->s_max_mnt_count)) {
369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		reason = _(" has been mounted %u times without being checked");
370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		reason_arg = fs->super->s_mnt_count;
371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (batt && (fs->super->s_mnt_count <
372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			     (unsigned) fs->super->s_max_mnt_count*2))
373116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch			reason = 0;
374116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch	} else if (!broken_system_clock && fs->super->s_checkinterval &&
375116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch		   (ctx->now < lastcheck)) {
376116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch		reason = _(" has filesystem last checked time in the future");
377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (batt)
378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			reason = 0;
379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	} else if (!broken_system_clock && fs->super->s_checkinterval &&
380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		   ((ctx->now - lastcheck) >=
381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		    ((time_t) fs->super->s_checkinterval))) {
382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		reason = _(" has gone %u days without being checked");
383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		reason_arg = (ctx->now - fs->super->s_lastcheck)/(3600*24);
384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (batt && ((ctx->now - fs->super->s_lastcheck) <
385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			     fs->super->s_checkinterval*2))
386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			reason = 0;
3871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	}
388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (reason) {
389ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch		log_out(ctx, "%s", ctx->device_name);
390ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch		log_out(ctx, reason, reason_arg);
391effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch		log_out(ctx, _(", check forced.\n"));
392ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch		return;
393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	/*
396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	 * Update the global counts from the block group counts.  This
3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 * is needed since modern kernels don't update the global
3985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 * counts so as to avoid locking the entire file system.  So
3995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 * if the filesystem is not unmounted cleanly, the global
4005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 * counts may not be accurate.  Update them here if we can,
4015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 * for the benefit of users who might examine the file system
4025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 * using dumpe2fs.  (This is for cosmetic reasons only.)
4035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 */
4045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	clear_problem_context(&pctx);
4055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	pctx.ino = fs->super->s_free_inodes_count;
4065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	pctx.ino2 = ctx->free_inodes;
4075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if ((pctx.ino != pctx.ino2) &&
4085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	    !(ctx->options & E2F_OPT_READONLY) &&
409a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	    fix_problem(ctx, PR_0_FREE_INODE_COUNT, &pctx)) {
410a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		fs->super->s_free_inodes_count = ctx->free_inodes;
411a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		ext2fs_mark_super_dirty(fs);
412a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	}
413a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	clear_problem_context(&pctx);
4145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	pctx.blk = ext2fs_free_blocks_count(fs->super);
4155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	pctx.blk2 = ctx->free_blocks;
4165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if ((pctx.blk != pctx.blk2) &&
4175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	    !(ctx->options & E2F_OPT_READONLY) &&
4185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	    fix_problem(ctx, PR_0_FREE_BLOCK_COUNT, &pctx)) {
4191320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci		ext2fs_free_blocks_count_set(fs->super, ctx->free_blocks);
4201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci		ext2fs_mark_super_dirty(fs);
4215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	}
4225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
4235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	/* Print the summary message when we're skipping a full check */
4245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	log_out(ctx, _("%s: clean, %u/%u files, %llu/%llu blocks"),
4255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		ctx->device_name,
4265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		fs->super->s_inodes_count - fs->super->s_free_inodes_count,
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		fs->super->s_inodes_count,
4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		ext2fs_blocks_count(fs->super) -
4295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		ext2fs_free_blocks_count(fs->super),
4305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		ext2fs_blocks_count(fs->super));
4315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	next_check = 100000;
4325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if (fs->super->s_max_mnt_count > 0) {
4335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		next_check = fs->super->s_max_mnt_count - fs->super->s_mnt_count;
4345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		if (next_check <= 0)
4355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			next_check = 1;
4365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	}
4375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if (!broken_system_clock && fs->super->s_checkinterval &&
4385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	    ((ctx->now - fs->super->s_lastcheck) >= fs->super->s_checkinterval))
4395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		next_check = 1;
4405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if (next_check <= 5) {
4415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		if (next_check == 1) {
4425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			if (batt)
4435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)				log_out(ctx, _(" (check deferred; "
4445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)					       "on battery)"));
4455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			else
4465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)				log_out(ctx, _(" (check after next mount)"));
4475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		} else
4485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			log_out(ctx, _(" (check in %ld mounts)"), next_check);
4495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	}
4505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	log_out(ctx, "\n");
4515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)skip:
4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	ext2fs_close(fs);
4535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	ctx->fs = NULL;
4545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	e2fsck_free_context(ctx);
455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	exit(FSCK_OK);
456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
4575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
458eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch/*
459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch * For completion notice
4605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */
4615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct percent_tbl {
4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	int	max_pass;
4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	int	table[32];
4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct percent_tbl e2fsck_tbl = {
4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	5, { 0, 70, 90, 92,  95, 100 }
4675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
4685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)static char bar[128], spaces[128];
469eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
4701320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccistatic float calc_percent(struct percent_tbl *tbl, int pass, int curr,
471eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			  int max)
472eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{
473eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	float	percent;
474eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
475eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (pass <= 0)
4765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		return 0.0;
4775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	if (pass > tbl->max_pass || max == 0)
4785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		return 100.0;
4795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	percent = ((float) curr) / ((float) max);
4805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	return ((percent * (tbl->table[pass] - tbl->table[pass-1]))
4815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		+ tbl->table[pass-1]);
4825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
4835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciextern void e2fsck_clear_progbar(e2fsck_t ctx)
4855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles){
4865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	if (!(ctx->flags & E2F_FLAG_PROG_BAR))
4875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		return;
4885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	printf("%s%s\r%s", ctx->start_meta, spaces + (sizeof(spaces) - 80),
4905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	       ctx->stop_meta);
4915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	fflush(stdout);
4925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	ctx->flags &= ~E2F_FLAG_PROG_BAR;
4935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
4945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
4955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)int e2fsck_simple_progress(e2fsck_t ctx, const char *label, float percent,
4965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			   unsigned int dpynum)
4975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles){
4985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	static const char spinner[] = "\\|/-";
4991320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	int	i;
5005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	unsigned int	tick;
5015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	struct timeval	tv;
5025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	int dpywidth;
5035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	int fixed_percent;
5045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	if (ctx->flags & E2F_FLAG_PROG_SUPPRESS)
5065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		return 0;
5075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	/*
5095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	 * Calculate the new progress position.  If the
5105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	 * percentage hasn't changed, then we skip out right
5115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	 * away.
5125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	 */
5135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	fixed_percent = (int) ((10 * percent) + 0.5);
5145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	if (ctx->progress_last_percent == fixed_percent)
5155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		return 0;
5165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	ctx->progress_last_percent = fixed_percent;
5175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	/*
5195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	 * If we've already updated the spinner once within
5205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	 * the last 1/8th of a second, no point doing it
5215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	 * again.
5225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	 */
5235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	gettimeofday(&tv, NULL);
5245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	tick = (tv.tv_sec << 3) + (tv.tv_usec / (1000000 / 8));
5255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	if ((tick == ctx->progress_last_time) &&
5261320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	    (fixed_percent != 0) && (fixed_percent != 1000))
5275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		return 0;
5285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	ctx->progress_last_time = tick;
5295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	/*
5315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	 * Advance the spinner, and note that the progress bar
5325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	 * will be on the screen
5335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	 */
5345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	ctx->progress_pos = (ctx->progress_pos+1) & 3;
5355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	ctx->flags |= E2F_FLAG_PROG_BAR;
5365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	dpywidth = 66 - strlen(label);
5385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	dpywidth = 8 * (dpywidth / 8);
5395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	if (dpynum)
5405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		dpywidth -= 8;
5415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	i = ((percent * dpywidth) + 50) / 100;
5435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	printf("%s%s: |%s%s", ctx->start_meta, label,
5445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	       bar + (sizeof(bar) - (i+1)),
5455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	       spaces + (sizeof(spaces) - (dpywidth - i + 1)));
5465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	if (fixed_percent == 1000)
5475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		fputc('|', stdout);
5485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	else
5495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		fputc(spinner[ctx->progress_pos & 3], stdout);
5505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	printf(" %4.1f%%  ", percent);
5515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	if (dpynum)
5525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		printf("%u\r", dpynum);
5535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	else
5545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		fputs(" \r", stdout);
5555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	fputs(ctx->stop_meta, stdout);
5565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	if (fixed_percent == 1000)
5581320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci		e2fsck_clear_progbar(ctx);
5591320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	fflush(stdout);
5605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	return 0;
5625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
5635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static int e2fsck_update_progress(e2fsck_t ctx, int pass,
5655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				  unsigned long cur, unsigned long max)
5665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles){
5675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	char buf[1024];
5685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	float percent;
5695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	if (pass == 0)
5715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		return 0;
5725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	if (ctx->progress_fd) {
5745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		snprintf(buf, sizeof(buf), "%d %lu %lu %s\n",
5755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			 pass, cur, max, ctx->device_name);
5765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		write_all(ctx->progress_fd, buf, strlen(buf));
5775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	} else {
5785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		percent = calc_percent(&e2fsck_tbl, pass, cur, max);
5795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		e2fsck_simple_progress(ctx, ctx->device_name,
5805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				       percent, 0);
5815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	}
5825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	return 0;
5835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
5845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#define PATH_SET "PATH=/sbin"
5865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)/*
5885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * Make sure 0,1,2 file descriptors are open, so that we don't open
5895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) * the filesystem using the same file descriptor as stdout or stderr.
5905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) */
5915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void reserve_stdio_fds(void)
5925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles){
5935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	int	fd = 0;
5945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
5955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	while (fd <= 2) {
5965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		fd = open("/dev/null", O_RDWR);
5975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		if (fd < 0) {
5985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			fprintf(stderr, _("ERROR: Couldn't open "
5995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				"/dev/null (%s)\n"),
6005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				strerror(errno));
6015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			break;
6025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		}
6035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	}
6045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
6055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifdef HAVE_SIGNAL_H
6075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void signal_progress_on(int sig EXT2FS_ATTR((unused)))
6085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles){
6091320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	e2fsck_t ctx = e2fsck_global_ctx;
6105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	if (!ctx)
6125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		return;
6135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	ctx->progress = e2fsck_update_progress;
6155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
6165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void signal_progress_off(int sig EXT2FS_ATTR((unused)))
6185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles){
6195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	e2fsck_t ctx = e2fsck_global_ctx;
6201320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
6215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	if (!ctx)
6225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		return;
6235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	e2fsck_clear_progbar(ctx);
6255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	ctx->progress = 0;
6265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
6275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void signal_cancel(int sig EXT2FS_ATTR((unused)))
6295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles){
6305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	e2fsck_t ctx = e2fsck_global_ctx;
6315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	if (!ctx)
6335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		exit(FSCK_CANCELED);
6345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	ctx->flags |= E2F_FLAG_CANCEL;
6365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
6375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
6385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void parse_extended_opts(e2fsck_t ctx, const char *opts)
6405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles){
6415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	char	*buf, *token, *next, *p, *arg;
6425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	int	ea_ver;
6435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	int	extended_usage = 0;
6445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
6455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	buf = string_copy(ctx, opts, 0);
6465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	for (token = buf; token && *token; token = next) {
6475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		p = strchr(token, ',');
6485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		next = 0;
6495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		if (p) {
6505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			*p = 0;
6515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			next = p+1;
6525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		}
6535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		arg = strchr(token, '=');
6545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		if (arg) {
6555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			*arg = 0;
6565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			arg++;
6575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		}
6585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		if (strcmp(token, "ea_ver") == 0) {
6595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			if (!arg) {
6605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				extended_usage++;
6615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				continue;
6621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci			}
6635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			ea_ver = strtoul(arg, &p, 0);
6645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			if (*p ||
6655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			    ((ea_ver != 1) && (ea_ver != 2))) {
6665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				fprintf(stderr,
6675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)					_("Invalid EA version.\n"));
6685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				extended_usage++;
6695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				continue;
6705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			}
6715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			ctx->ext_attr_ver = ea_ver;
6725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		} else if (strcmp(token, "fragcheck") == 0) {
6735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			ctx->options |= E2F_OPT_FRAGCHECK;
6745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			continue;
6755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		} else if (strcmp(token, "journal_only") == 0) {
6765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			if (arg) {
6775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				extended_usage++;
6785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				continue;
6795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			}
6805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			ctx->options |= E2F_OPT_JOURNAL_ONLY;
6815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		} else if (strcmp(token, "discard") == 0) {
6825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			ctx->options |= E2F_OPT_DISCARD;
6835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			continue;
6845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		} else if (strcmp(token, "nodiscard") == 0) {
6855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			ctx->options &= ~E2F_OPT_DISCARD;
6865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			continue;
6875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		} else if (strcmp(token, "log_filename") == 0) {
6885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			if (!arg)
6895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				extended_usage++;
6905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			else
6915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				ctx->log_fn = string_copy(ctx, arg, 0);
6925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			continue;
6935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		} else {
6941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci			fprintf(stderr, _("Unknown extended option: %s\n"),
6951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci				token);
6965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			extended_usage++;
6975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		}
6985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	}
6995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	free(buf);
7005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	if (extended_usage) {
7025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		fputs(("\nExtended options are separated by commas, "
7035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		       "and may take an argument which\n"
7045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		       "is set off by an equals ('=') sign.  "
7055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		       "Valid extended options are:\n"), stderr);
7065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		fputs(("\tea_ver=<ea_version (1 or 2)>\n"), stderr);
7075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		fputs(("\tfragcheck\n"), stderr);
7085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		fputs(("\tjournal_only\n"), stderr);
7095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		fputs(("\tdiscard\n"), stderr);
7105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		fputs(("\tnodiscard\n"), stderr);
7115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		fputc('\n', stderr);
7125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		exit(1);
7135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	}
7145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
7155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static void syntax_err_report(const char *filename, long err, int line_num)
7175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles){
7185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	fprintf(stderr,
7195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		_("Syntax error in e2fsck config file (%s, line #%d)\n\t%s\n"),
7205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		filename, line_num, error_message(err));
7215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	exit(FSCK_ERROR);
7225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)}
7235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static const char *config_fn[] = { ROOT_SYSCONFDIR "/e2fsck.conf", 0 };
7255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static errcode_t PRS(int argc, char *argv[], e2fsck_t *ret_ctx)
7275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles){
7285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	int		flush = 0;
7295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	int		c, fd;
7305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifdef MTRACE
7315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	extern void	*mallwatch;
7325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
7335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	e2fsck_t	ctx;
7345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	errcode_t	retval;
7355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifdef HAVE_SIGNAL_H
7365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	struct sigaction	sa;
7375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
7385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	char		*extended_opts = 0;
7395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	char		*cp;
7405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	int 		res;		/* result of sscanf */
7415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifdef CONFIG_JBD_DEBUG
7425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	char 		*jbd_debug;
7435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#endif
7445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	retval = e2fsck_allocate_context(&ctx);
7465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	if (retval)
7475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		return retval;
7485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	*ret_ctx = ctx;
7505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	setvbuf(stdout, NULL, _IONBF, BUFSIZ);
7525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	setvbuf(stderr, NULL, _IONBF, BUFSIZ);
7535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	if (isatty(0) && isatty(1)) {
7545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		ctx->interactive = 1;
7555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	} else {
7561320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci		ctx->start_meta[0] = '\001';
7575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		ctx->stop_meta[0] = '\002';
7585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	}
7595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	memset(bar, '=', sizeof(bar)-1);
7605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	memset(spaces, ' ', sizeof(spaces)-1);
7615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	add_error_table(&et_ext2_error_table);
7625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	add_error_table(&et_prof_error_table);
7635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	blkid_get_cache(&ctx->blkid, NULL);
7645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	if (argc && *argv)
7665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		ctx->program_name = *argv;
7675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	else
7685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		ctx->program_name = "e2fsck";
7695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	while ((c = getopt (argc, argv, "panyrcC:B:dE:fvtFVM:b:I:j:P:l:L:N:SsDk")) != EOF)
7711320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci		switch (c) {
7725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		case 'C':
7735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			ctx->progress = e2fsck_update_progress;
7745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			res = sscanf(optarg, "%d", &ctx->progress_fd);
7755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			if (res != 1)
7765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				goto sscanf_err;
7775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)
7785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			if (ctx->progress_fd < 0) {
7795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				ctx->progress = 0;
7805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				ctx->progress_fd = ctx->progress_fd * -1;
7815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			}
7825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			if (!ctx->progress_fd)
7835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				break;
7845f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			/* Validate the file descriptor to avoid disasters */
7855f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			fd = dup(ctx->progress_fd);
7865f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			if (fd < 0) {
7875f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				fprintf(stderr,
7885f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				_("Error validating file descriptor %d: %s\n"),
7895f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)					ctx->progress_fd,
7905f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)					error_message(errno));
7915f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				fatal_error(ctx,
7925f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			_("Invalid completion information file descriptor"));
7935f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			} else
7945f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				close(fd);
7955f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			break;
7965f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		case 'D':
7975f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			ctx->options |= E2F_OPT_COMPRESS_DIRS;
7981320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci			break;
7995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		case 'E':
8005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			extended_opts = optarg;
8015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			break;
8025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		case 'p':
8035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		case 'a':
8045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			if (ctx->options & (E2F_OPT_YES|E2F_OPT_NO)) {
8055f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			conflict_opt:
8065f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				fatal_error(ctx,
8075f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)	_("Only one of the options -p/-a, -n or -y may be specified."));
8085f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			}
8095f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			ctx->options |= E2F_OPT_PREEN;
8105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			break;
8115f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		case 'n':
8125f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			if (ctx->options & (E2F_OPT_YES|E2F_OPT_PREEN))
8135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				goto conflict_opt;
8145f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			ctx->options |= E2F_OPT_NO;
8155f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			break;
8165f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		case 'y':
8175f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			if (ctx->options & (E2F_OPT_PREEN|E2F_OPT_NO))
8185f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				goto conflict_opt;
8195f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			ctx->options |= E2F_OPT_YES;
8205f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			break;
8215f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		case 't':
8225f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#ifdef RESOURCE_TRACK
8235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			if (ctx->options & E2F_OPT_TIME)
8245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				ctx->options |= E2F_OPT_TIME2;
8255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			else
8265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				ctx->options |= E2F_OPT_TIME;
8275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)#else
8285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			fprintf(stderr, _("The -t option is not "
8295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				"supported on this version of e2fsck.\n"));
8301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif
8311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci			break;
8325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		case 'c':
8335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			if (cflag++)
8345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				ctx->options |= E2F_OPT_WRITECHECK;
8355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			ctx->options |= E2F_OPT_CHECKBLOCKS;
8365f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			break;
8375f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		case 'r':
8385f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			/* What we do by default, anyway! */
8395f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			break;
8405f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		case 'b':
8415f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			res = sscanf(optarg, "%llu", &ctx->use_superblock);
8425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			if (res != 1)
8435f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				goto sscanf_err;
8445f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			ctx->flags |= E2F_FLAG_SB_SPECIFIED;
8455f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			break;
8465f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		case 'B':
8475f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			ctx->blocksize = atoi(optarg);
8485f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			break;
8495f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		case 'I':
8505f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			res = sscanf(optarg, "%d", &ctx->inode_buffer_blocks);
8515f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			if (res != 1)
8525f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				goto sscanf_err;
8535f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			break;
8545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		case 'j':
8555f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			ctx->journal_name = blkid_get_devname(ctx->blkid,
8565f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)							      optarg, NULL);
8575f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			if (!ctx->journal_name) {
8585f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				com_err(ctx->program_name, 0,
8595f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)					_("Unable to resolve '%s'"),
8605f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)					optarg);
8615f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				fatal_error(ctx, 0);
8625f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			}
8635f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			break;
8645f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		case 'P':
8655f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			res = sscanf(optarg, "%d", &ctx->process_inode_size);
8665f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			if (res != 1)
8675f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)				goto sscanf_err;
8685f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			break;
8695f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		case 'L':
8705f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			replace_bad_blocks++;
8715f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		case 'l':
8725f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			bad_blocks_file = string_copy(ctx, optarg, 0);
8735f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			break;
8745f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		case 'd':
8755f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			ctx->options |= E2F_OPT_DEBUG;
8765f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			break;
8775f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		case 'f':
8785f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			ctx->options |= E2F_OPT_FORCE;
8795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			break;
8805f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		case 'F':
8815f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			flush = 1;
8825f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)			break;
8835f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)		case 'v':
884eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			verbose = 1;
885eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			break;
886eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		case 'V':
887eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			show_version_only = 1;
888eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			break;
889eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#ifdef MTRACE
890eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		case 'M':
891eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			mallwatch = (void *) strtol(optarg, NULL, 0);
892eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			break;
893eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
894424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		case 'N':
895424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)			ctx->device_name = string_copy(ctx, optarg, 0);
896424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)			break;
897eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		case 'k':
898eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			keep_bad_blocks++;
899eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			break;
900eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		default:
901eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			usage(ctx);
902424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		}
903424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)	if (show_version_only)
904424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		return 0;
905424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)	if (optind != argc - 1)
906424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)		usage(ctx);
907424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)	if ((ctx->options & E2F_OPT_NO) &&
908eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	    (ctx->options & E2F_OPT_COMPRESS_DIRS)) {
909eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		com_err(ctx->program_name, 0,
910eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			_("The -n and -D options are incompatible."));
911eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		fatal_error(ctx, 0);
912eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
913eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if ((ctx->options & E2F_OPT_NO) && cflag) {
914116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch		com_err(ctx->program_name, 0,
915116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch			_("The -n and -c options are incompatible."));
916116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch		fatal_error(ctx, 0);
917116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch	}
918eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if ((ctx->options & E2F_OPT_NO) && bad_blocks_file) {
919eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		com_err(ctx->program_name, 0,
920eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			_("The -n and -l/-L options are incompatible."));
921eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		fatal_error(ctx, 0);
922eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
923eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (ctx->options & E2F_OPT_NO)
924eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		ctx->options |= E2F_OPT_READONLY;
9251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
926eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	ctx->io_options = strchr(argv[optind], '?');
927eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (ctx->io_options)
9281320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci		*ctx->io_options++ = 0;
929eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	ctx->filesystem_name = blkid_get_devname(ctx->blkid, argv[optind], 0);
930ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch	if (!ctx->filesystem_name) {
931ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch		com_err(ctx->program_name, 0, _("Unable to resolve '%s'"),
932effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch			argv[optind]);
933ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch		fatal_error(ctx, 0);
934eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
935eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (extended_opts)
936eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		parse_extended_opts(ctx, extended_opts);
937eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
9385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if ((cp = getenv("E2FSCK_CONFIG")) != NULL)
9395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		config_fn[0] = cp;
9405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	profile_set_syntax_err_cb(syntax_err_report);
9415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	profile_init(config_fn, &ctx->profile);
9425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	profile_get_boolean(ctx->profile, "options", "report_time", 0, 0,
9445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			    &c);
9455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if (c)
9465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		ctx->options |= E2F_OPT_TIME | E2F_OPT_TIME2;
9475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	profile_get_boolean(ctx->profile, "options", "report_verbose", 0, 0,
9485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			    &c);
9495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if (c)
950a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		verbose = 1;
951a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
952a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	/* Turn off discard in read-only mode */
953a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	if ((ctx->options & E2F_OPT_NO) &&
954a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	    (ctx->options & E2F_OPT_DISCARD))
9555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		ctx->options &= ~E2F_OPT_DISCARD;
9565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if (flush) {
9585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		fd = open(ctx->filesystem_name, O_RDONLY, 0);
9595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		if (fd < 0) {
9601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci			com_err("open", errno,
9611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci				_("while opening %s for flushing"),
9625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)				ctx->filesystem_name);
9635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			fatal_error(ctx, 0);
9645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		}
9655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		if ((retval = ext2fs_sync_device(fd, 1))) {
9665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			com_err("ext2fs_sync_device", retval,
9675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)				_("while trying to flush %s"),
9685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)				ctx->filesystem_name);
9695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			fatal_error(ctx, 0);
9705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		}
9715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		close(fd);
9725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	}
9735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if (cflag && bad_blocks_file) {
9745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		fprintf(stderr, _("The -c and the -l/-L options may "
9755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)				  "not be both used at the same time.\n"));
9765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		exit(FSCK_USAGE);
9775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	}
9785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifdef HAVE_SIGNAL_H
9795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	/*
9805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 * Set up signal action
9815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	 */
9825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	memset(&sa, 0, sizeof(struct sigaction));
9835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	sa.sa_handler = signal_cancel;
9845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	sigaction(SIGINT, &sa, 0);
9855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	sigaction(SIGTERM, &sa, 0);
9865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifdef SA_RESTART
9875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	sa.sa_flags = SA_RESTART;
9885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
9895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	e2fsck_global_ctx = ctx;
9905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	sa.sa_handler = signal_progress_on;
9915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	sigaction(SIGUSR1, &sa, 0);
9925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	sa.sa_handler = signal_progress_off;
9935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	sigaction(SIGUSR2, &sa, 0);
9945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
9955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
9965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	/* Update our PATH to include /sbin if we need to run badblocks  */
997eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (cflag) {
998eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		char *oldpath = getenv("PATH");
999eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		char *newpath;
1000eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		int len = sizeof(PATH_SET) + 1;
1001eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
10025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		if (oldpath)
10035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			len += strlen(oldpath);
10045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
10055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		newpath = malloc(len);
10065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		if (!newpath)
10075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			fatal_error(ctx, "Couldn't malloc() newpath");
10085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		strcpy(newpath, PATH_SET);
10095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
10105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		if (oldpath) {
1011eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			strcat(newpath, ":");
1012eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			strcat(newpath, oldpath);
1013eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		}
1014eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		putenv(newpath);
1015eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
1016eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#ifdef CONFIG_JBD_DEBUG
1017eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	jbd_debug = getenv("E2FSCK_JBD_DEBUG");
1018eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (jbd_debug) {
1019eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		res = sscanf(jbd_debug, "%d", &journal_enable_debug);
1020eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (res != 1) {
1021eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			fprintf(stderr,
1022eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			        _("E2FSCK_JBD_DEBUG \"%s\" not an integer\n\n"),
1023eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			        jbd_debug);
1024eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			exit (1);
1025eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		}
1026eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
1027eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
1028eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	return 0;
1029eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1030eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochsscanf_err:
1031116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch	fprintf(stderr, _("\nInvalid non-numeric argument to -%c (\"%s\")\n\n"),
1032116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch	        c, optarg);
1033116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch	exit (1);
1034116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
1035eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1036eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic errcode_t try_open_fs(e2fsck_t ctx, int flags, io_manager io_ptr,
1037eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			     ext2_filsys *ret_fs)
1038eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{
1039eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	errcode_t retval;
1040eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1041eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	*ret_fs = NULL;
10421320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci	if (ctx->superblock && ctx->blocksize) {
1043eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
1044eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				      flags, ctx->superblock, ctx->blocksize,
10451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci				      io_ptr, ret_fs);
1046eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	} else if (ctx->superblock) {
1047ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch		int blocksize;
1048ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch		for (blocksize = EXT2_MIN_BLOCK_SIZE;
1049effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch		     blocksize <= EXT2_MAX_BLOCK_SIZE; blocksize *= 2) {
1050ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch			if (*ret_fs) {
1051eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				ext2fs_free(*ret_fs);
1052eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				*ret_fs = NULL;
1053eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			}
1054eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			retval = ext2fs_open2(ctx->filesystem_name,
10555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)					      ctx->io_options, flags,
10565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)					      ctx->superblock, blocksize,
10575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)					      io_ptr, ret_fs);
10585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)			if (!retval)
10595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)				break;
10605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		}
10615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	} else
10625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		retval = ext2fs_open2(ctx->filesystem_name, ctx->io_options,
10635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)				      flags, 0, 0, io_ptr, ret_fs);
10645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
10655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)	if (ret_fs)
10665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)		e2fsck_set_bitmap_type(*ret_fs, EXT2FS_BMAP64_RBTREE,
1067a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)				       "default", NULL);
1068a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	return retval;
1069a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)}
1070a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1071a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)static const char *my_ver_string = E2FSPROGS_VERSION;
1072eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic const char *my_ver_date = E2FSPROGS_DATE;
1073eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1074eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochstatic int e2fsck_check_mmp(ext2_filsys fs, e2fsck_t ctx)
1075eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{
1076eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	struct mmp_struct *mmp_s;
1077eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	unsigned int mmp_check_interval;
1078eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	errcode_t retval = 0;
1079eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	struct problem_context pctx;
1080eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	unsigned int wait_time = 0;
1081eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1082eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	clear_problem_context(&pctx);
1083eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (fs->mmp_buf == NULL) {
1084eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		retval = ext2fs_get_mem(fs->blocksize, &fs->mmp_buf);
1085eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (retval)
1086eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			goto check_error;
1087eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
1088116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
1089116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch	retval = ext2fs_mmp_read(fs, fs->super->s_mmp_block, fs->mmp_buf);
1090116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch	if (retval)
1091116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch		goto check_error;
1092eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1093eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	mmp_s = fs->mmp_buf;
1094eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1095eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	mmp_check_interval = fs->super->s_mmp_update_interval;
1096eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (mmp_check_interval < EXT4_MMP_MIN_CHECK_INTERVAL)
1097eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		mmp_check_interval = EXT4_MMP_MIN_CHECK_INTERVAL;
1098eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1099eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	/*
1100eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	 * If check_interval in MMP block is larger, use that instead of
1101eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	 * check_interval from the superblock.
1102a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	 */
1103a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	if (mmp_s->mmp_check_interval > mmp_check_interval)
1104a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		mmp_check_interval = mmp_s->mmp_check_interval;
1105a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1106a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	wait_time = mmp_check_interval * 2 + 1;
1107eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1108eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (mmp_s->mmp_seq == EXT4_MMP_SEQ_CLEAN)
1109eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		retval = 0;
1110eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	else if (mmp_s->mmp_seq == EXT4_MMP_SEQ_FSCK)
1111eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		retval = EXT2_ET_MMP_FSCK_ON;
1112eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	else if (mmp_s->mmp_seq > EXT4_MMP_SEQ_MAX)
1113eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		retval = EXT2_ET_MMP_UNKNOWN_SEQ;
1114eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1115eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (retval)
1116eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		goto check_error;
1117eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1118eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	/* Print warning if e2fck will wait for more than 20 secs. */
1119eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (verbose || wait_time > EXT4_MMP_MIN_CHECK_INTERVAL * 4) {
1120eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		log_out(ctx, _("MMP interval is %u seconds and total wait "
1121eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			       "time is %u seconds. Please wait...\n"),
1122eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			mmp_check_interval, wait_time * 2);
1123eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
1124eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1125eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	return 0;
1126eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1127eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochcheck_error:
1128eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1129eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (retval == EXT2_ET_MMP_BAD_BLOCK) {
1130eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (fix_problem(ctx, PR_0_MMP_INVALID_BLK, &pctx)) {
1131eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			fs->super->s_mmp_block = 0;
1132eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			ext2fs_mark_super_dirty(fs);
1133a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)			retval = 0;
1134a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		}
1135a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	} else if (retval == EXT2_ET_MMP_FAILED) {
1136a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		com_err(ctx->program_name, retval,
1137a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)			_("while checking MMP block"));
1138eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		dump_mmp_msg(fs->mmp_buf, NULL);
1139eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	} else if (retval == EXT2_ET_MMP_FSCK_ON ||
1140eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		   retval == EXT2_ET_MMP_UNKNOWN_SEQ) {
1141eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		com_err(ctx->program_name, retval,
1142eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			_("while checking MMP block"));
1143eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		dump_mmp_msg(fs->mmp_buf,
1144eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			     _("If you are sure the filesystem is not "
1145eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			       "in use on any node, run:\n"
1146eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			       "'tune2fs -f -E clear_mmp {device}'\n"));
1147eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	} else if (retval == EXT2_ET_MMP_MAGIC_INVALID) {
1148eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (fix_problem(ctx, PR_0_MMP_INVALID_MAGIC, &pctx)) {
1149eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			ext2fs_mmp_clear(fs);
1150eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			retval = 0;
1151eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		}
1152eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
1153eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	return retval;
1154eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch}
1155eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1156eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochint main (int argc, char *argv[])
1157eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch{
1158eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	errcode_t	retval = 0, retval2 = 0, orig_retval = 0;
1159eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	int		exit_value = FSCK_OK;
1160eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	ext2_filsys	fs = 0;
1161eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	io_manager	io_ptr;
1162eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	struct ext2_super_block *sb;
1163eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	const char	*lib_ver_date;
1164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	int		my_ver, lib_ver;
1165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	e2fsck_t	ctx;
1166a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	blk_t		orig_superblock;
1167a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	struct problem_context pctx;
1168a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	int flags, run_result;
1169a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	int journal_size;
1170eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	int sysval, sys_page_size = 4096;
1171eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	int old_bitmaps;
1172eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	__u32 features[3];
1173eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	char *cp;
1174eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	int qtype;  /* quota type */
1175eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1176eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	clear_problem_context(&pctx);
1177eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	sigcatcher_setup();
1178eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#ifdef MTRACE
1179eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	mtrace();
1180eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
1181eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#ifdef MCHECK
1182eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	mcheck(0);
1183eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
1184eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#ifdef ENABLE_NLS
1185eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	setlocale(LC_MESSAGES, "");
1186eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	setlocale(LC_CTYPE, "");
1187eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
1188eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	textdomain(NLS_CAT_NAME);
1189eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	set_com_err_gettext(gettext);
1190eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
1191eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	my_ver = ext2fs_parse_version_string(my_ver_string);
1192eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	lib_ver = ext2fs_get_library_version(0, &lib_ver_date);
1193a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	if (my_ver > lib_ver) {
1194a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		fprintf( stderr, _("Error: ext2fs library version "
1195a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)			"out of date!\n"));
1196a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		show_version_only++;
1197a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	}
1198eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1199eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	retval = PRS(argc, argv, &ctx);
1200eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (retval) {
1201eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		com_err("e2fsck", retval,
1202eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			_("while trying to initialize program"));
1203eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		exit(FSCK_ERROR);
1204eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
1205eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	reserve_stdio_fds();
1206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1207eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	set_up_logging(ctx);
1208eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (ctx->logf) {
1209eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		int i;
1210eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		fputs("E2fsck run: ", ctx->logf);
1211eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		for (i = 0; i < argc; i++) {
1212eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			if (i)
1213eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				fputc(' ', ctx->logf);
1214eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			fputs(argv[i], ctx->logf);
1215eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		}
1216eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		fputc('\n', ctx->logf);
1217eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
1218a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1219a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	init_resource_track(&ctx->global_rtrack, NULL);
1220a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	if (!(ctx->options & E2F_OPT_PREEN) || show_version_only)
1221a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		log_err(ctx, "e2fsck %s (%s)\n", my_ver_string,
1222a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)			 my_ver_date);
1223eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1224eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (show_version_only) {
1225eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		log_err(ctx, _("\tUsing %s, %s\n"),
1226eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			error_message(EXT2_ET_BASE), lib_ver_date);
1227eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		exit(FSCK_OK);
1228ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch	}
12291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
1230ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch	check_mount(ctx);
1231eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1232eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (!(ctx->options & E2F_OPT_PREEN) &&
1233eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	    !(ctx->options & E2F_OPT_NO) &&
1234eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	    !(ctx->options & E2F_OPT_YES)) {
1235eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (!ctx->interactive)
1236eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			fatal_error(ctx,
1237eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				    _("need terminal for interactive repairs"));
1238eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
1239eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	ctx->superblock = ctx->use_superblock;
1240a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1241a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	flags = EXT2_FLAG_SKIP_MMP;
1242a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)restart:
1243a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)#ifdef CONFIG_TESTIO_DEBUG
1244a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) {
1245eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		io_ptr = test_io_manager;
1246eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		test_io_backing_manager = unix_io_manager;
1247eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	} else
1248eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
1249eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		io_ptr = unix_io_manager;
1250eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	flags |= EXT2_FLAG_NOFREE_ON_ERROR;
1251eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	profile_get_boolean(ctx->profile, "options", "old_bitmaps", 0, 0,
1252a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)			    &old_bitmaps);
1253a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	if (!old_bitmaps)
1254a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		flags |= EXT2_FLAG_64BITS;
1255a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	if ((ctx->options & E2F_OPT_READONLY) == 0) {
1256a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		flags |= EXT2_FLAG_RW;
1257a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		if (!(ctx->mount_flags & EXT2_MF_ISROOT &&
1258a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)		      ctx->mount_flags & EXT2_MF_READONLY))
1259eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			flags |= EXT2_FLAG_EXCLUSIVE;
1260eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if ((ctx->mount_flags & EXT2_MF_READONLY) &&
1261eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		    (ctx->options & E2F_OPT_FORCE))
1262eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			flags &= ~EXT2_FLAG_EXCLUSIVE;
1263a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	}
1264a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1265a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	retval = try_open_fs(ctx, flags, io_ptr, &fs);
1266a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)
1267a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	if (!ctx->superblock && !(ctx->options & E2F_OPT_PREEN) &&
1268a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	    !(ctx->flags & E2F_FLAG_SB_SPECIFIED) &&
1269a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)	    ((retval == EXT2_ET_BAD_MAGIC) ||
1270eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	     (retval == EXT2_ET_CORRUPT_SUPERBLOCK) ||
1271eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	     ((retval == 0) && (retval2 = ext2fs_check_desc(fs))))) {
1272eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (retval) {
1273eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			pctx.errcode = retval;
1274eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			fix_problem(ctx, PR_0_OPEN_FAILED, &pctx);
1275eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		}
1276eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (retval2) {
1277eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			pctx.errcode = retval2;
1278eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			fix_problem(ctx, PR_0_CHECK_DESC_FAILED, &pctx);
1279eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		}
1280eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		pctx.errcode = 0;
1281eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (retval2 == ENOMEM || retval2 == EXT2_ET_NO_MEMORY) {
1282eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			retval = retval2;
1283eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			goto failure;
1284eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		}
1285eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (fs->flags & EXT2_FLAG_NOFREE_ON_ERROR) {
1286eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			ext2fs_free(fs);
1287eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			fs = NULL;
1288eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		}
1289eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (!fs || (fs->group_desc_count > 1)) {
1290eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			log_out(ctx, _("%s: %s trying backup blocks...\n"),
1291eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				ctx->program_name,
1292eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				retval ? _("Superblock invalid,") :
1293eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				_("Group descriptors look bad..."));
1294eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			orig_superblock = ctx->superblock;
1295eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			get_backup_sb(ctx, fs, ctx->filesystem_name, io_ptr);
1296eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			if (fs)
1297eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				ext2fs_close(fs);
1298eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			orig_retval = retval;
1299eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			retval = try_open_fs(ctx, flags, io_ptr, &fs);
1300eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			if ((orig_retval == 0) && retval != 0) {
1301eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				if (fs)
1302eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch					ext2fs_close(fs);
1303eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				log_out(ctx, _("%s: %s while using the "
1304eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch					       "backup blocks"),
1305eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch					ctx->program_name,
1306eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch					error_message(retval));
1307eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				log_out(ctx, _("%s: going back to original "
1308eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch					       "superblock\n"),
1309eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch					ctx->program_name);
1310eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				ctx->superblock = orig_superblock;
1311eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				retval = try_open_fs(ctx, flags, io_ptr, &fs);
1312eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			}
1313eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		}
1314eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
1315eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (((retval == EXT2_ET_UNSUPP_FEATURE) ||
1316eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	     (retval == EXT2_ET_RO_UNSUPP_FEATURE)) &&
1317eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	    fs && fs->super) {
1318eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		sb = fs->super;
1319eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		features[0] = (sb->s_feature_compat &
1320eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			       ~EXT2_LIB_FEATURE_COMPAT_SUPP);
1321eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		features[1] = (sb->s_feature_incompat &
1322eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			       ~EXT2_LIB_FEATURE_INCOMPAT_SUPP);
1323eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		features[2] = (sb->s_feature_ro_compat &
1324eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			       ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP);
1325eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (features[0] || features[1] || features[2])
1326eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			goto print_unsupp_features;
1327eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
1328eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdochfailure:
1329eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (retval) {
1330eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (orig_retval)
1331eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			retval = orig_retval;
1332eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		com_err(ctx->program_name, retval, _("while trying to open %s"),
1333eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			ctx->filesystem_name);
1334eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (retval == EXT2_ET_REV_TOO_HIGH) {
1335eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			log_out(ctx, _("The filesystem revision is apparently "
1336eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			       "too high for this version of e2fsck.\n"
1337eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			       "(Or the filesystem superblock "
1338eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			       "is corrupt)\n\n"));
1339eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
1340eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		} else if (retval == EXT2_ET_SHORT_READ)
1341eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			log_out(ctx, _("Could this be a zero-length "
1342eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				       "partition?\n"));
1343eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		else if ((retval == EPERM) || (retval == EACCES))
1344eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			log_out(ctx, _("You must have %s access to the "
1345eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			       "filesystem or be root\n"),
1346eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			       (ctx->options & E2F_OPT_READONLY) ?
1347eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			       "r/o" : "r/w");
1348eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		else if (retval == ENXIO)
1349eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			log_out(ctx, _("Possibly non-existent or "
1350eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				       "swap device?\n"));
1351eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		else if (retval == EBUSY)
1352eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			log_out(ctx, _("Filesystem mounted or opened "
1353eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				 "exclusively by another program?\n"));
1354eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		else if (retval == ENOENT)
1355eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			log_out(ctx, _("Possibly non-existent device?\n"));
1356eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#ifdef EROFS
1357eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		else if (retval == EROFS)
1358eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			log_out(ctx, _("Disk write-protected; use the -n "
1359eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				       "option to do a read-only\n"
1360eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				       "check of the device.\n"));
1361eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch#endif
1362eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		else
1363eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			fix_problem(ctx, PR_0_SB_CORRUPT, &pctx);
1364eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		fatal_error(ctx, 0);
1365eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
1366eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	/*
1367eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	 * We only update the master superblock because (a) paranoia;
1368eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	 * we don't want to corrupt the backup superblocks, and (b) we
1369eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	 * don't need to update the mount count and last checked
1370eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	 * fields in the backup superblock (the kernel doesn't update
1371eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	 * the backup superblocks anyway).  With newer versions of the
1372eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	 * library this flag is set by ext2fs_open2(), but we set this
1373eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	 * here just to be sure.  (No, we don't support e2fsck running
1374eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	 * with some other libext2fs than the one that it was shipped
1375eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	 * with, but just in case....)
1376eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	 */
1377eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	fs->flags |= EXT2_FLAG_MASTER_SB_ONLY;
1378eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1379eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (!(ctx->flags & E2F_FLAG_GOT_DEVSIZE)) {
1380eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		__u32 blocksize = EXT2_BLOCK_SIZE(fs->super);
1381eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		int need_restart = 0;
1382eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1383eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		pctx.errcode = ext2fs_get_device_size2(ctx->filesystem_name,
1384eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch						       blocksize,
1385eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch						       &ctx->num_blocks);
1386eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		/*
1387eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		 * The floppy driver refuses to allow anyone else to
1388eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		 * open the device if has been opened with O_EXCL;
1389eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		 * this is unlike other block device drivers in Linux.
1390eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		 * To handle this, we close the filesystem and then
1391eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		 * reopen the filesystem after we get the device size.
1392eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		 */
1393eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (pctx.errcode == EBUSY) {
1394eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			ext2fs_close(fs);
1395eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			need_restart++;
1396eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			pctx.errcode =
1397eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch				ext2fs_get_device_size2(ctx->filesystem_name,
1398eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch							blocksize,
1399eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch							&ctx->num_blocks);
1400eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		}
1401eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (pctx.errcode == EXT2_ET_UNIMPLEMENTED)
1402eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			ctx->num_blocks = 0;
1403eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		else if (pctx.errcode) {
1404eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			fix_problem(ctx, PR_0_GETSIZE_ERROR, &pctx);
1405eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			ctx->flags |= E2F_FLAG_ABORT;
1406eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			fatal_error(ctx, 0);
1407eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		}
1408eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		ctx->flags |= E2F_FLAG_GOT_DEVSIZE;
1409eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (need_restart)
1410eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			goto restart;
1411eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
1412eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1413eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	ctx->fs = fs;
1414eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	fs->priv_data = ctx;
1415eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	fs->now = ctx->now;
1416eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	sb = fs->super;
1417eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1418eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (sb->s_rev_level > E2FSCK_CURRENT_REV) {
1419eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		com_err(ctx->program_name, EXT2_ET_REV_TOO_HIGH,
1420eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			_("while trying to open %s"),
1421eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			ctx->filesystem_name);
1422eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	get_newer:
1423eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		fatal_error(ctx, _("Get a newer version of e2fsck!"));
1424eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
1425eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1426eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	/*
1427eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	 * Set the device name, which is used whenever we print error
1428eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	 * or informational messages to the user.
1429eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	 */
1430eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (ctx->device_name == 0 &&
1431eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	    (sb->s_volume_name[0] != 0)) {
1432eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		ctx->device_name = string_copy(ctx, sb->s_volume_name,
1433eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch					       sizeof(sb->s_volume_name));
1434eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
1435eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (ctx->device_name == 0)
1436eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		ctx->device_name = string_copy(ctx, ctx->filesystem_name, 0);
1437eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	for (cp = ctx->device_name; *cp; cp++)
1438eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (isspace(*cp) || *cp == ':')
1439eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			*cp = '_';
1440eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1441eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	ehandler_init(fs->io);
1442eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1443eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if ((fs->super->s_feature_incompat & EXT4_FEATURE_INCOMPAT_MMP) &&
1444eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	    (flags & EXT2_FLAG_SKIP_MMP)) {
1445eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		if (e2fsck_check_mmp(fs, ctx))
1446eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			fatal_error(ctx, 0);
1447eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1448eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		/*
1449eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		 * Restart in order to reopen fs but this time start mmp.
1450eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		 */
1451eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		ext2fs_close(fs);
1452eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		ctx->fs = NULL;
1453eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		flags &= ~EXT2_FLAG_SKIP_MMP;
1454eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		goto restart;
1455eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	}
1456eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1457eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	if (ctx->logf)
1458eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch		fprintf(ctx->logf, "Filesystem UUID: %s\n",
1459eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch			e2p_uuid2str(sb->s_uuid));
1460eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch
1461eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	/*
1462eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	 * Make sure the ext3 superblock fields are consistent.
1463eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch	 */
1464f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)	retval = e2fsck_check_ext3_journal(ctx);
1465	if (retval) {
1466		com_err(ctx->program_name, retval,
1467			_("while checking ext3 journal for %s"),
1468			ctx->device_name);
1469		fatal_error(ctx, 0);
1470	}
1471
1472	/*
1473	 * Check to see if we need to do ext3-style recovery.  If so,
1474	 * do it, and then restart the fsck.
1475	 */
1476	if (sb->s_feature_incompat & EXT3_FEATURE_INCOMPAT_RECOVER) {
1477		if (ctx->options & E2F_OPT_READONLY) {
1478			log_out(ctx, _("Warning: skipping journal recovery "
1479				       "because doing a read-only filesystem "
1480				       "check.\n"));
1481			io_channel_flush(ctx->fs->io);
1482		} else {
1483			if (ctx->flags & E2F_FLAG_RESTARTED) {
1484				/*
1485				 * Whoops, we attempted to run the
1486				 * journal twice.  This should never
1487				 * happen, unless the hardware or
1488				 * device driver is being bogus.
1489				 */
1490				com_err(ctx->program_name, 0,
1491					_("unable to set superblock flags on %s\n"), ctx->device_name);
1492				fatal_error(ctx, 0);
1493			}
1494			retval = e2fsck_run_ext3_journal(ctx);
1495			if (retval) {
1496				com_err(ctx->program_name, retval,
1497				_("while recovering ext3 journal of %s"),
1498					ctx->device_name);
1499				fatal_error(ctx, 0);
1500			}
1501			ext2fs_close(ctx->fs);
1502			ctx->fs = 0;
1503			ctx->flags |= E2F_FLAG_RESTARTED;
1504			goto restart;
1505		}
1506	}
1507
1508	/*
1509	 * Check for compatibility with the feature sets.  We need to
1510	 * be more stringent than ext2fs_open().
1511	 */
1512	features[0] = sb->s_feature_compat & ~EXT2_LIB_FEATURE_COMPAT_SUPP;
1513	features[1] = sb->s_feature_incompat & ~EXT2_LIB_FEATURE_INCOMPAT_SUPP;
1514	features[2] = (sb->s_feature_ro_compat &
1515		       ~EXT2_LIB_FEATURE_RO_COMPAT_SUPP);
1516print_unsupp_features:
1517	if (features[0] || features[1] || features[2]) {
1518		int	i, j;
1519		__u32	*mask = features, m;
1520
1521		log_err(ctx, _("%s has unsupported feature(s):"),
1522			ctx->filesystem_name);
1523
1524		for (i=0; i <3; i++,mask++) {
1525			for (j=0,m=1; j < 32; j++, m<<=1) {
1526				if (*mask & m)
1527					log_err(ctx, " %s",
1528						e2p_feature2string(i, m));
1529			}
1530		}
1531		log_err(ctx, "\n");
1532		goto get_newer;
1533	}
1534#ifdef ENABLE_COMPRESSION
1535	if (sb->s_feature_incompat & EXT2_FEATURE_INCOMPAT_COMPRESSION)
1536		log_err(ctx, _("%s: warning: compression support "
1537			       "is experimental.\n"),
1538			ctx->program_name);
1539#endif
1540#ifndef ENABLE_HTREE
1541	if (sb->s_feature_compat & EXT2_FEATURE_COMPAT_DIR_INDEX) {
1542		log_err(ctx, _("%s: e2fsck not compiled with HTREE support,\n\t"
1543			  "but filesystem %s has HTREE directories.\n"),
1544			ctx->program_name, ctx->device_name);
1545		goto get_newer;
1546	}
1547#endif
1548
1549	/*
1550	 * If the user specified a specific superblock, presumably the
1551	 * master superblock has been trashed.  So we mark the
1552	 * superblock as dirty, so it can be written out.
1553	 */
1554	if (ctx->superblock &&
1555	    !(ctx->options & E2F_OPT_READONLY))
1556		ext2fs_mark_super_dirty(fs);
1557
1558	/*
1559	 * Calculate the number of filesystem blocks per pagesize.  If
1560	 * fs->blocksize > page_size, set the number of blocks per
1561	 * pagesize to 1 to avoid division by zero errors.
1562	 */
1563#ifdef _SC_PAGESIZE
1564	sysval = sysconf(_SC_PAGESIZE);
1565	if (sysval > 0)
1566		sys_page_size = sysval;
1567#endif /* _SC_PAGESIZE */
1568	ctx->blocks_per_page = sys_page_size / fs->blocksize;
1569	if (ctx->blocks_per_page == 0)
1570		ctx->blocks_per_page = 1;
1571
1572	if (ctx->superblock)
1573		set_latch_flags(PR_LATCH_RELOC, PRL_LATCHED, 0);
1574	ext2fs_mark_valid(fs);
1575	check_super_block(ctx);
1576	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
1577		fatal_error(ctx, 0);
1578	check_if_skip(ctx);
1579	check_resize_inode(ctx);
1580	if (bad_blocks_file)
1581		read_bad_blocks_file(ctx, bad_blocks_file, replace_bad_blocks);
1582	else if (cflag)
1583		read_bad_blocks_file(ctx, 0, !keep_bad_blocks); /* Test disk */
1584	if (ctx->flags & E2F_FLAG_SIGNAL_MASK)
1585		fatal_error(ctx, 0);
1586
1587	/*
1588	 * Mark the system as valid, 'til proven otherwise
1589	 */
1590	ext2fs_mark_valid(fs);
1591
1592	retval = ext2fs_read_bb_inode(fs, &fs->badblocks);
1593	if (retval) {
1594		log_out(ctx, _("%s: %s while reading bad blocks inode\n"),
1595			ctx->program_name, error_message(retval));
1596		preenhalt(ctx);
1597		log_out(ctx, _("This doesn't bode well, "
1598			       "but we'll try to go on...\n"));
1599	}
1600
1601	/*
1602	 * Save the journal size in megabytes.
1603	 * Try and use the journal size from the backup else let e2fsck
1604	 * find the default journal size.
1605	 */
1606	if (sb->s_jnl_backup_type == EXT3_JNL_BACKUP_BLOCKS)
1607		journal_size = (sb->s_jnl_blocks[15] << (32 - 20)) |
1608			       (sb->s_jnl_blocks[16] >> 20);
1609	else
1610		journal_size = -1;
1611
1612	if (sb->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_QUOTA) {
1613		/* Quotas were enabled. Do quota accounting during fsck. */
1614		if ((sb->s_usr_quota_inum && sb->s_grp_quota_inum) ||
1615		    (!sb->s_usr_quota_inum && !sb->s_grp_quota_inum))
1616			qtype = -1;
1617		else
1618			qtype = sb->s_usr_quota_inum ? USRQUOTA : GRPQUOTA;
1619
1620		quota_init_context(&ctx->qctx, ctx->fs, qtype);
1621	}
1622
1623	run_result = e2fsck_run(ctx);
1624	e2fsck_clear_progbar(ctx);
1625
1626	if (ctx->flags & E2F_FLAG_JOURNAL_INODE) {
1627		if (fix_problem(ctx, PR_6_RECREATE_JOURNAL, &pctx)) {
1628			if (journal_size < 1024)
1629				journal_size = ext2fs_default_journal_size(ext2fs_blocks_count(fs->super));
1630			if (journal_size < 0) {
1631				fs->super->s_feature_compat &=
1632					~EXT3_FEATURE_COMPAT_HAS_JOURNAL;
1633				fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
1634				log_out(ctx, "%s: Couldn't determine "
1635					"journal size\n", ctx->program_name);
1636				goto no_journal;
1637			}
1638			log_out(ctx, _("Creating journal (%d blocks): "),
1639			       journal_size);
1640			fflush(stdout);
1641			retval = ext2fs_add_journal_inode(fs,
1642							  journal_size, 0);
1643			if (retval) {
1644				log_out(ctx, "%s: while trying to create "
1645					"journal\n", error_message(retval));
1646				goto no_journal;
1647			}
1648			log_out(ctx, _(" Done.\n"));
1649			log_out(ctx, _("\n*** journal has been re-created - "
1650				       "filesystem is now ext3 again ***\n"));
1651		}
1652	}
1653no_journal:
1654
1655	if (ctx->qctx) {
1656		int i, needs_writeout;
1657		for (i = 0; i < MAXQUOTAS; i++) {
1658			if (qtype != -1 && qtype != i)
1659				continue;
1660			needs_writeout = 0;
1661			pctx.num = i;
1662			retval = quota_compare_and_update(ctx->qctx, i,
1663							  &needs_writeout);
1664			if ((retval || needs_writeout) &&
1665			    fix_problem(ctx, PR_6_UPDATE_QUOTAS, &pctx))
1666				quota_write_inode(ctx->qctx, i);
1667		}
1668		quota_release_context(&ctx->qctx);
1669	}
1670
1671	if (run_result == E2F_FLAG_RESTART) {
1672		log_out(ctx, _("Restarting e2fsck from the beginning...\n"));
1673		retval = e2fsck_reset_context(ctx);
1674		if (retval) {
1675			com_err(ctx->program_name, retval,
1676				_("while resetting context"));
1677			fatal_error(ctx, 0);
1678		}
1679		ext2fs_close(fs);
1680		goto restart;
1681	}
1682	if (run_result & E2F_FLAG_CANCEL) {
1683		log_out(ctx, _("%s: e2fsck canceled.\n"), ctx->device_name ?
1684			ctx->device_name : ctx->filesystem_name);
1685		exit_value |= FSCK_CANCELED;
1686	}
1687	if (run_result & E2F_FLAG_ABORT)
1688		fatal_error(ctx, _("aborted"));
1689	if (check_backup_super_block(ctx)) {
1690		fs->flags &= ~EXT2_FLAG_MASTER_SB_ONLY;
1691		ext2fs_mark_super_dirty(fs);
1692	}
1693
1694#ifdef MTRACE
1695	mtrace_print("Cleanup");
1696#endif
1697	if (ext2fs_test_changed(fs)) {
1698		exit_value |= FSCK_NONDESTRUCT;
1699		if (!(ctx->options & E2F_OPT_PREEN))
1700			log_out(ctx, _("\n%s: ***** FILE SYSTEM WAS "
1701				       "MODIFIED *****\n"),
1702				ctx->device_name);
1703		if (ctx->mount_flags & EXT2_MF_ISROOT) {
1704			log_out(ctx, _("%s: ***** REBOOT LINUX *****\n"),
1705				ctx->device_name);
1706			exit_value |= FSCK_REBOOT;
1707		}
1708	}
1709	if (!ext2fs_test_valid(fs) ||
1710	    ((exit_value & FSCK_CANCELED) &&
1711	     (sb->s_state & EXT2_ERROR_FS))) {
1712		log_out(ctx, _("\n%s: ********** WARNING: Filesystem still has "
1713			       "errors **********\n\n"), ctx->device_name);
1714		exit_value |= FSCK_UNCORRECTED;
1715		exit_value &= ~FSCK_NONDESTRUCT;
1716	}
1717	if (exit_value & FSCK_CANCELED) {
1718		int	allow_cancellation;
1719
1720		profile_get_boolean(ctx->profile, "options",
1721				    "allow_cancellation", 0, 0,
1722				    &allow_cancellation);
1723		exit_value &= ~FSCK_NONDESTRUCT;
1724		if (allow_cancellation && ext2fs_test_valid(fs) &&
1725		    (sb->s_state & EXT2_VALID_FS) &&
1726		    !(sb->s_state & EXT2_ERROR_FS))
1727			exit_value = 0;
1728	} else {
1729		show_stats(ctx);
1730		if (!(ctx->options & E2F_OPT_READONLY)) {
1731			if (ext2fs_test_valid(fs)) {
1732				if (!(sb->s_state & EXT2_VALID_FS))
1733					exit_value |= FSCK_NONDESTRUCT;
1734				sb->s_state = EXT2_VALID_FS;
1735			} else
1736				sb->s_state &= ~EXT2_VALID_FS;
1737			sb->s_mnt_count = 0;
1738			if (!(ctx->flags & E2F_FLAG_TIME_INSANE))
1739				sb->s_lastcheck = ctx->now;
1740			memset(((char *) sb) + EXT4_S_ERR_START, 0,
1741			       EXT4_S_ERR_LEN);
1742			ext2fs_mark_super_dirty(fs);
1743		}
1744	}
1745
1746	if ((run_result & E2F_FLAG_CANCEL) == 0 &&
1747	    sb->s_feature_ro_compat & EXT4_FEATURE_RO_COMPAT_GDT_CSUM &&
1748	    !(ctx->options & E2F_OPT_READONLY)) {
1749		retval = ext2fs_set_gdt_csum(ctx->fs);
1750		if (retval) {
1751			com_err(ctx->program_name, retval,
1752				_("while setting block group checksum info"));
1753			fatal_error(ctx, 0);
1754		}
1755	}
1756
1757	e2fsck_write_bitmaps(ctx);
1758	io_channel_flush(ctx->fs->io);
1759	print_resource_track(ctx, NULL, &ctx->global_rtrack, ctx->fs->io);
1760
1761	ext2fs_close(fs);
1762	ctx->fs = NULL;
1763	free(ctx->journal_name);
1764
1765	e2fsck_free_context(ctx);
1766	remove_error_table(&et_ext2_error_table);
1767	remove_error_table(&et_prof_error_table);
1768	return exit_value;
1769}
1770