13839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o/*
23839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o * util.c --- miscellaneous utilities
3efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o *
421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
521c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o *
621c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * %Begin-Header%
721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * This file may be redistributed under the terms of the GNU Public
821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * License.
921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o * %End-Header%
103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o */
113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
123839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <stdlib.h>
1380875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o#include <stdio.h>
143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <unistd.h>
153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <string.h>
163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <ctype.h>
1780875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o#ifdef __linux__
1880875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o#include <sys/utsname.h>
1980875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o#endif
209ecd8becf46c32ed18e468fe647947b359d25cdbTheodore Ts'o
219ecd8becf46c32ed18e468fe647947b359d25cdbTheodore Ts'o#ifdef HAVE_CONIO_H
229ecd8becf46c32ed18e468fe647947b359d25cdbTheodore Ts'o#undef HAVE_TERMIOS_H
239ecd8becf46c32ed18e468fe647947b359d25cdbTheodore Ts'o#include <conio.h>
24e6597048d9d1637c9f997363a7f45c74b98fd0e2Theodore Ts'o#define read_a_char()	getch()
259ecd8becf46c32ed18e468fe647947b359d25cdbTheodore Ts'o#else
269ecd8becf46c32ed18e468fe647947b359d25cdbTheodore Ts'o#ifdef HAVE_TERMIOS_H
273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include <termios.h>
289ecd8becf46c32ed18e468fe647947b359d25cdbTheodore Ts'o#endif
299ecd8becf46c32ed18e468fe647947b359d25cdbTheodore Ts'o#endif
309ecd8becf46c32ed18e468fe647947b359d25cdbTheodore Ts'o
314a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o#ifdef HAVE_MALLOC_H
324a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o#include <malloc.h>
334a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o#endif
343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
3549a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos#ifdef HAVE_ERRNO_H
3649a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos#include <errno.h>
3749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos#endif
3849a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos
393839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#include "e2fsck.h"
403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
41aa75ecccab67ea7428fc19c66e80a28fb1ca941fTheodore Ts'oextern e2fsck_t e2fsck_global_ctx;   /* Try your very best not to use this! */
42542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o
43e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <stdarg.h>
44e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#include <time.h>
4550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <sys/time.h>
4650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#include <sys/resource.h>
4750e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o
48f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'ovoid fatal_error(e2fsck_t ctx, const char *msg)
493839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
50e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	ext2_filsys fs = ctx->fs;
51e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	int exit_value = FSCK_ERROR;
52e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
53efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o	if (msg)
541b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		fprintf (stderr, "e2fsck: %s\n", msg);
55e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (!fs)
56e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		goto out;
57e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (fs->io && fs->super) {
58e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		ext2fs_mmp_stop(ctx->fs);
59e39ac92269d645bd279c2660d127b47159b8b1f9Theodore Ts'o		if (ctx->fs->io->magic == EXT2_ET_MAGIC_IO_CHANNEL)
6058a75177cabbea82361d037978485b2d656c8c89Theodore Ts'o			io_channel_flush(ctx->fs->io);
6158a75177cabbea82361d037978485b2d656c8c89Theodore Ts'o		else
62e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			log_err(ctx, "e2fsck: io manager magic bad!\n");
63e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
64e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (ext2fs_test_changed(fs)) {
65e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		exit_value |= FSCK_NONDESTRUCT;
66e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		log_out(ctx, _("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
67e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			ctx->device_name);
68e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (ctx->mount_flags & EXT2_MF_ISROOT)
69e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			exit_value |= FSCK_REBOOT;
70e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
71e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (!ext2fs_test_valid(fs)) {
72e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		log_out(ctx, _("\n%s: ********** WARNING: Filesystem still has "
73e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			       "errors **********\n\n"), ctx->device_name);
74e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		exit_value |= FSCK_UNCORRECTED;
75e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		exit_value &= ~FSCK_NONDESTRUCT;
7613dcce8bb46961fcab14e87343e25aaebef7f44cEric Sandeen	}
77e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallout:
78f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o	ctx->flags |= E2F_FLAG_ABORT;
79f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o	if (ctx->flags & E2F_FLAG_SETJMP_OK)
80f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o		longjmp(ctx->abort_loc, 1);
81e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	exit(exit_value);
82e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}
83e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
84e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallvoid log_out(e2fsck_t ctx, const char *fmt, ...)
85e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{
86e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	va_list pvar;
87e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
88e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	va_start(pvar, fmt);
89e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	vprintf(fmt, pvar);
90e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	va_end(pvar);
91e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (ctx->logf) {
92e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		va_start(pvar, fmt);
93e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		vfprintf(ctx->logf, fmt, pvar);
94e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		va_end(pvar);
95e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
96e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}
97e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
98e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallvoid log_err(e2fsck_t ctx, const char *fmt, ...)
99e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{
100e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	va_list pvar;
101e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
102e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	va_start(pvar, fmt);
103e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	vfprintf(stderr, fmt, pvar);
104e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	va_end(pvar);
105e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (ctx->logf) {
106e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		va_start(pvar, fmt);
107e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		vfprintf(ctx->logf, fmt, pvar);
108e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		va_end(pvar);
109e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
110b0e91c89257d906324d6081c952157f768dfc699Theodore Ts'o}
111b0e91c89257d906324d6081c952157f768dfc699Theodore Ts'o
112f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'ovoid *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
113f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o			     const char *description)
1143839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
1153839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	void *ret;
1163839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	char buf[256];
1173839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
1183839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#ifdef DEBUG_ALLOCATE_MEMORY
119611378fe20777da83fcc8fe77ff2c515b7dc1e42Andreas Dilger	printf("Allocating %u bytes for %s...\n", size, description);
1203839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif
1213839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	ret = malloc(size);
1223839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (!ret) {
123e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		sprintf(buf, "Can't allocate %u bytes for %s\n",
124e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			size, description);
125f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o		fatal_error(ctx, buf);
1263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
1273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	memset(ret, 0, size);
1283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return ret;
1293839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
1303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
131efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'ochar *string_copy(e2fsck_t ctx EXT2FS_ATTR((unused)),
132544349270e4c74a6feb971123884a8cf5052a7eeTheodore Ts'o		  const char *str, int len)
133f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o{
134f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o	char	*ret;
135efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
136f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o	if (!str)
137f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o		return NULL;
138f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o	if (!len)
139f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o		len = strlen(str);
140f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o	ret = malloc(len+1);
141f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o	if (ret) {
142f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o		strncpy(ret, str, len);
143f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o		ret[len] = 0;
144f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o	}
145f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o	return ret;
146f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o}
147f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o
148f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o#ifndef HAVE_STRNLEN
149f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o/*
150f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o * Incredibly, libc5 doesn't appear to have strnlen.  So we have to
151f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o * provide our own.
152f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o */
153f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'oint e2fsck_strnlen(const char * s, int count)
154f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o{
155f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o	const char *cp = s;
156f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o
157f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o	while (count-- && *cp)
158f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o		cp++;
159f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o	return cp - s;
160f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o}
161f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o#endif
162f364093b1956def0b0f1d037852cbb645284d5f2Theodore Ts'o
163542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o#ifndef HAVE_CONIO_H
1643e69906495d5898849a6154b0311b5d4a84a27aeTheodore Ts'ostatic int read_a_char(void)
165542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o{
166542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o	char	c;
167542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o	int	r;
168542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o	int	fail = 0;
169542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o
170542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o	while(1) {
171542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o		if (e2fsck_global_ctx &&
172542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o		    (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
173542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o			return 3;
174542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o		}
175542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o		r = read(0, &c, 1);
176542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o		if (r == 1)
177542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o			return c;
178542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o		if (fail++ > 100)
179542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o			break;
180542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o	}
181542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o	return EOF;
182542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o}
183542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o#endif
184542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o
185e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallint ask_yn(e2fsck_t ctx, const char * string, int def)
1863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
1873839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	int		c;
1883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	const char	*defstr;
18953ef44c40a3e425d2c700d8fd77a6b655aa121feTheodore Ts'o	const char	*short_yes = _("yY");
19053ef44c40a3e425d2c700d8fd77a6b655aa121feTheodore Ts'o	const char	*short_no = _("nN");
1913839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
1929ecd8becf46c32ed18e468fe647947b359d25cdbTheodore Ts'o#ifdef HAVE_TERMIOS_H
1939ecd8becf46c32ed18e468fe647947b359d25cdbTheodore Ts'o	struct termios	termios, tmp;
1949ecd8becf46c32ed18e468fe647947b359d25cdbTheodore Ts'o
1953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	tcgetattr (0, &termios);
1963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	tmp = termios;
1973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	tmp.c_lflag &= ~(ICANON | ECHO);
19850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	tmp.c_cc[VMIN] = 1;
19950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	tmp.c_cc[VTIME] = 0;
2003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	tcsetattr (0, TCSANOW, &tmp);
2019ecd8becf46c32ed18e468fe647947b359d25cdbTheodore Ts'o#endif
2023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
2033839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (def == 1)
204542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o		defstr = _(_("<y>"));
2053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	else if (def == 0)
206542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o		defstr = _(_("<n>"));
2073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	else
2080c4a07264e55b42c6e30230e66b1dea7d4b94ea9Theodore Ts'o		defstr = _(" (y/n)");
209e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	log_out(ctx, "%s%s? ", string, defstr);
2103839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	while (1) {
2113839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		fflush (stdout);
212e6597048d9d1637c9f997363a7f45c74b98fd0e2Theodore Ts'o		if ((c = read_a_char()) == EOF)
2133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			break;
214542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o		if (c == 3) {
215542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o#ifdef HAVE_TERMIOS_H
216542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o			tcsetattr (0, TCSANOW, &termios);
217542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o#endif
218e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			if (ctx->flags & E2F_FLAG_SETJMP_OK) {
219e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				log_out(ctx, "\n");
220542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o				longjmp(e2fsck_global_ctx->abort_loc, 1);
221542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o			}
222e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			log_out(ctx, "%s", _("cancelled!\n"));
223542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o			return 0;
224542867fb705f0c5705365e470f3e3dd097b5bdedTheodore Ts'o		}
2250c4a07264e55b42c6e30230e66b1dea7d4b94ea9Theodore Ts'o		if (strchr(short_yes, (char) c)) {
2263839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			def = 1;
2273839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			break;
2283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
2290c4a07264e55b42c6e30230e66b1dea7d4b94ea9Theodore Ts'o		else if (strchr(short_no, (char) c)) {
2303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			def = 0;
2313839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			break;
2323839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		}
233e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		else if ((c == 27 || c == ' ' || c == '\n') && (def != -1))
2343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o			break;
2353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
2363839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (def)
237e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		log_out(ctx, "%s", _("yes\n"));
2383839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	else
239e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		log_out(ctx, "%s", _("no\n"));
2409ecd8becf46c32ed18e468fe647947b359d25cdbTheodore Ts'o#ifdef HAVE_TERMIOS_H
2413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	tcsetattr (0, TCSANOW, &termios);
2429ecd8becf46c32ed18e468fe647947b359d25cdbTheodore Ts'o#endif
2433839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return def;
2443839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
2453839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
2461b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'oint ask (e2fsck_t ctx, const char * string, int def)
2473839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
2481b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (ctx->options & E2F_OPT_NO) {
249e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		log_out(ctx, _("%s? no\n\n"), string);
2503839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		return 0;
2513839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
2521b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (ctx->options & E2F_OPT_YES) {
253e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		log_out(ctx, _("%s? yes\n\n"), string);
2543839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		return 1;
2553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
2561b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (ctx->options & E2F_OPT_PREEN) {
257e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		log_out(ctx, "%s? %s\n\n", string, def ? _("yes") : _("no"));
2583839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		return def;
2593839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
260e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	return ask_yn(ctx, string, def);
2613839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
2623839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
263f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'ovoid e2fsck_read_bitmaps(e2fsck_t ctx)
2643839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
2651b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	ext2_filsys fs = ctx->fs;
2663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	errcode_t	retval;
267e94bc631648299dca43a6015520b18f6232d50dfTheodore Ts'o	const char	*old_op;
268e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	unsigned int	save_type;
2693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
2701b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (ctx->invalid_bitmaps) {
2711b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		com_err(ctx->program_name, 0,
2720c4a07264e55b42c6e30230e66b1dea7d4b94ea9Theodore Ts'o		    _("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
2731b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			ctx->device_name);
274f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o		fatal_error(ctx, 0);
2753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
276f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
277e94bc631648299dca43a6015520b18f6232d50dfTheodore Ts'o	old_op = ehandler_operation(_("reading inode and block bitmaps"));
278e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	e2fsck_set_bitmap_type(fs, EXT2FS_BMAP64_RBTREE, "fs_bitmaps",
279e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			       &save_type);
280f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	retval = ext2fs_read_bitmaps(fs);
281e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	fs->default_bitmap_type = save_type;
282e94bc631648299dca43a6015520b18f6232d50dfTheodore Ts'o	ehandler_operation(old_op);
283f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	if (retval) {
2841b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o		com_err(ctx->program_name, retval,
2850c4a07264e55b42c6e30230e66b1dea7d4b94ea9Theodore Ts'o			_("while retrying to read bitmaps for %s"),
2861b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o			ctx->device_name);
287f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o		fatal_error(ctx, 0);
2883839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
2893839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
2903839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
291f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'ovoid e2fsck_write_bitmaps(e2fsck_t ctx)
2923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
2931b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	ext2_filsys fs = ctx->fs;
2943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	errcode_t	retval;
295e94bc631648299dca43a6015520b18f6232d50dfTheodore Ts'o	const char	*old_op;
2963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
2971bb6f6c87e860f8c021f966fc36aa8768590a227Andreas Dilger	old_op = ehandler_operation(_("writing block and inode bitmaps"));
2981bb6f6c87e860f8c021f966fc36aa8768590a227Andreas Dilger	retval = ext2fs_write_bitmaps(fs);
2991bb6f6c87e860f8c021f966fc36aa8768590a227Andreas Dilger	ehandler_operation(old_op);
3001bb6f6c87e860f8c021f966fc36aa8768590a227Andreas Dilger	if (retval) {
3011bb6f6c87e860f8c021f966fc36aa8768590a227Andreas Dilger		com_err(ctx->program_name, retval,
3021bb6f6c87e860f8c021f966fc36aa8768590a227Andreas Dilger			_("while rewriting block and inode bitmaps for %s"),
3031bb6f6c87e860f8c021f966fc36aa8768590a227Andreas Dilger			ctx->device_name);
3041bb6f6c87e860f8c021f966fc36aa8768590a227Andreas Dilger		fatal_error(ctx, 0);
3053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	}
3063839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
3073839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
3081b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'ovoid preenhalt(e2fsck_t ctx)
3093839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
3101b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	ext2_filsys fs = ctx->fs;
3111b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o
3121b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (!(ctx->options & E2F_OPT_PREEN))
3133839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		return;
314e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	log_err(ctx, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
3150c4a07264e55b42c6e30230e66b1dea7d4b94ea9Theodore Ts'o		"RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
3161b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	       ctx->device_name);
31779cc33628256e817610e921ddf600f72e4f879e1Eric Sandeen	ctx->flags |= E2F_FLAG_EXITING;
31850e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	if (fs != NULL) {
31950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		fs->super->s_state |= EXT2_ERROR_FS;
32050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		ext2fs_mark_super_dirty(fs);
32150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o		ext2fs_close(fs);
32250e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	}
3233839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	exit(FSCK_UNCORRECTED);
3243839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
3253839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
3268bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#ifdef RESOURCE_TRACK
3276d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'ovoid init_resource_track(struct resource_track *track, io_channel channel)
3283839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
32950e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#ifdef HAVE_GETRUSAGE
3303839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	struct rusage r;
33150e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif
3326d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o	io_stats io_start = 0;
333efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
3343839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	track->brk_start = sbrk(0);
3353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	gettimeofday(&track->time_start, 0);
33650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#ifdef HAVE_GETRUSAGE
33753ef44c40a3e425d2c700d8fd77a6b655aa121feTheodore Ts'o#ifdef sun
33853ef44c40a3e425d2c700d8fd77a6b655aa121feTheodore Ts'o	memset(&r, 0, sizeof(struct rusage));
3391b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o#endif
3403839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	getrusage(RUSAGE_SELF, &r);
3413839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	track->user_start = r.ru_utime;
3423839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	track->system_start = r.ru_stime;
34350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#else
34450e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	track->user_start.tv_sec = track->user_start.tv_usec = 0;
34550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o	track->system_start.tv_sec = track->system_start.tv_usec = 0;
34650e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif
3476d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o	track->bytes_read = 0;
3486d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o	track->bytes_written = 0;
3496d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o	if (channel && channel->manager && channel->manager->get_stats)
3506d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o		channel->manager->get_stats(channel, &io_start);
3516d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o	if (io_start) {
3526d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o		track->bytes_read = io_start->bytes_read;
3536d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o		track->bytes_written = io_start->bytes_written;
3546d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o	}
3553839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
3563839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
35721c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#ifdef __GNUC__
35821c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#define _INLINE_ __inline__
35921c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#else
36021c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#define _INLINE_
36121c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o#endif
36221c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o
36321c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'ostatic _INLINE_ float timeval_subtract(struct timeval *tv1,
36421c84b71e205b5ab13f14343da5645dcc985856dTheodore Ts'o				       struct timeval *tv2)
3653839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
3663839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	return ((tv1->tv_sec - tv2->tv_sec) +
3673839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
3683839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
3693839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
3709facd076ae8af6e908e228392cea866ce0faf1bcKen Chenvoid print_resource_track(e2fsck_t ctx, const char *desc,
3719facd076ae8af6e908e228392cea866ce0faf1bcKen Chen			  struct resource_track *track, io_channel channel)
3723839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
37350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#ifdef HAVE_GETRUSAGE
3743839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	struct rusage r;
37550e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif
3764a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o#ifdef HAVE_MALLINFO
3774a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o	struct mallinfo	malloc_info;
3784a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o#endif
3793839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	struct timeval time_end;
3803839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
3819facd076ae8af6e908e228392cea866ce0faf1bcKen Chen	if ((desc && !(ctx->options & E2F_OPT_TIME2)) ||
3829facd076ae8af6e908e228392cea866ce0faf1bcKen Chen	    (!desc && !(ctx->options & E2F_OPT_TIME)))
3839facd076ae8af6e908e228392cea866ce0faf1bcKen Chen		return;
3849facd076ae8af6e908e228392cea866ce0faf1bcKen Chen
3859facd076ae8af6e908e228392cea866ce0faf1bcKen Chen	e2fsck_clear_progbar(ctx);
3863839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	gettimeofday(&time_end, 0);
3871b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o
3881b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o	if (desc)
389e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		log_out(ctx, "%s: ", desc);
3904a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o
3914a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o#ifdef HAVE_MALLINFO
39270eabde9a581d340837c98b11d3ced324155d1aeAndreas Dilger#define kbytes(x)	(((unsigned long)(x) + 1023) / 1024)
393efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
3944a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o	malloc_info = mallinfo();
395e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	log_out(ctx, _("Memory used: %luk/%luk (%luk/%luk), "),
396e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		kbytes(malloc_info.arena), kbytes(malloc_info.hblkhd),
397e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		kbytes(malloc_info.uordblks), kbytes(malloc_info.fordblks));
3984a9f59366b3c5503bde40e9566dc996a0a40626fTheodore Ts'o#else
399e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	log_out(ctx, _("Memory used: %lu, "),
400e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		(unsigned long) (((char *) sbrk(0)) -
401e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				 ((char *) track->brk_start)));
402efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o#endif
40350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#ifdef HAVE_GETRUSAGE
4043839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	getrusage(RUSAGE_SELF, &r);
4053839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
406e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	log_out(ctx, _("time: %5.2f/%5.2f/%5.2f\n"),
407e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		timeval_subtract(&time_end, &track->time_start),
408e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		timeval_subtract(&r.ru_utime, &track->user_start),
409e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		timeval_subtract(&r.ru_stime, &track->system_start));
41050e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#else
411e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	log_out(ctx, _("elapsed time: %6.3f\n"),
412e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		timeval_subtract(&time_end, &track->time_start));
41350e1e10fa0ac12a3e2a9d20a75ee9041873cda96Theodore Ts'o#endif
4146d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o#define mbytes(x)	(((x) + 1048575) / 1048576)
4156d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o	if (channel && channel->manager && channel->manager->get_stats) {
4166d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o		io_stats delta = 0;
4176d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o		unsigned long long bytes_read = 0;
4186d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o		unsigned long long bytes_written = 0;
4196d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o
4206d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o		if (desc)
421e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			log_out(ctx, "%s: ", desc);
4226d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o
4236d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o		channel->manager->get_stats(channel, &delta);
4246d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o		if (delta) {
4256d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o			bytes_read = delta->bytes_read - track->bytes_read;
426efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o			bytes_written = delta->bytes_written -
4276d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o				track->bytes_written;
4286d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o		}
429e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		log_out(ctx, "I/O read: %lluMB, write: %lluMB, "
430e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			"rate: %.2fMB/s\n",
431e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			mbytes(bytes_read), mbytes(bytes_written),
432e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			(double)mbytes(bytes_read + bytes_written) /
433e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			timeval_subtract(&time_end, &track->time_start));
4346d96b00d57d236e2746f8245df6c8ea64abc64c1Theodore Ts'o	}
4353839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
4368bf191e8660939687ef35c013066d2082cb16722Theodore Ts'o#endif /* RESOURCE_TRACK */
4373839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
43808b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'ovoid e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
439f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o			      struct ext2_inode * inode, const char *proc)
440f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o{
441e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	errcode_t retval;
442f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
44308b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o	retval = ext2fs_read_inode(ctx->fs, ino, inode);
444f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	if (retval) {
445f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		com_err("ext2fs_read_inode", retval,
446611378fe20777da83fcc8fe77ff2c515b7dc1e42Andreas Dilger			_("while reading inode %lu in %s"), ino, proc);
447f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o		fatal_error(ctx, 0);
448f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	}
449f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o}
450f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
451fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilgervoid e2fsck_read_inode_full(e2fsck_t ctx, unsigned long ino,
452fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger			    struct ext2_inode *inode, int bufsize,
453fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger			    const char *proc)
454fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger{
455e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	errcode_t retval;
456fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger
457fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger	retval = ext2fs_read_inode_full(ctx->fs, ino, inode, bufsize);
458fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger	if (retval) {
459fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger		com_err("ext2fs_read_inode_full", retval,
460611378fe20777da83fcc8fe77ff2c515b7dc1e42Andreas Dilger			_("while reading inode %lu in %s"), ino, proc);
461fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger		fatal_error(ctx, 0);
462fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger	}
463fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger}
464fefaef39e046781ddc75d15a8f12369f17dbd17dAndreas Dilger
465e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallvoid e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
466e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			     struct ext2_inode * inode, int bufsize,
467e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			     const char *proc)
468cebe48a1ece8b9f61271c73ead83b59c8b36233eTheodore Ts'o{
469e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	errcode_t retval;
470cebe48a1ece8b9f61271c73ead83b59c8b36233eTheodore Ts'o
471cebe48a1ece8b9f61271c73ead83b59c8b36233eTheodore Ts'o	retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
472cebe48a1ece8b9f61271c73ead83b59c8b36233eTheodore Ts'o	if (retval) {
473cebe48a1ece8b9f61271c73ead83b59c8b36233eTheodore Ts'o		com_err("ext2fs_write_inode", retval,
474611378fe20777da83fcc8fe77ff2c515b7dc1e42Andreas Dilger			_("while writing inode %lu in %s"), ino, proc);
475cebe48a1ece8b9f61271c73ead83b59c8b36233eTheodore Ts'o		fatal_error(ctx, 0);
476cebe48a1ece8b9f61271c73ead83b59c8b36233eTheodore Ts'o	}
477cebe48a1ece8b9f61271c73ead83b59c8b36233eTheodore Ts'o}
478cebe48a1ece8b9f61271c73ead83b59c8b36233eTheodore Ts'o
479e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallvoid e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
480e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			struct ext2_inode * inode, const char *proc)
481f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o{
482e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	errcode_t retval;
483f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
48408b213017f8371ce4b56ad4d368eb0f92211d04eTheodore Ts'o	retval = ext2fs_write_inode(ctx->fs, ino, inode);
485f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	if (retval) {
486f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o		com_err("ext2fs_write_inode", retval,
487611378fe20777da83fcc8fe77ff2c515b7dc1e42Andreas Dilger			_("while writing inode %lu in %s"), ino, proc);
488f8188fff23dc2d9c9f858fb21264e46b17672825Theodore Ts'o		fatal_error(ctx, 0);
489f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o	}
490f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o}
491f3db3566b5e1342e49dffc5ec3f418a838584194Theodore Ts'o
4923839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#ifdef MTRACE
4933839e65723771b85975f4263102dd3ceec4523cTheodore Ts'ovoid mtrace_print(char *mesg)
4943839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o{
4953839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	FILE	*malloc_get_mallstream();
4963839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	FILE	*f = malloc_get_mallstream();
4973839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
4983839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o	if (f)
4993839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o		fprintf(f, "============= %s\n", mesg);
5003839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o}
5013839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o#endif
5023839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
503e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallblk64_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
504e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		      io_manager manager)
5051b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o{
506f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o	struct ext2_super_block *sb;
507f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o	io_channel		io = NULL;
508fae9bfaa5c1dc8b1bd6190d1a51024031e5ac9cfTheodore Ts'o	void			*buf = NULL;
509f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o	int			blocksize;
510e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	blk64_t			superblock, ret_sb = 8193;
511efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
512f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o	if (fs && fs->super) {
513f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o		ret_sb = (fs->super->s_blocks_per_group +
514f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o			  fs->super->s_first_data_block);
515f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o		if (ctx) {
516f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o			ctx->superblock = ret_sb;
517f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o			ctx->blocksize = fs->blocksize;
518f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o		}
519f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o		return ret_sb;
520f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o	}
521efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
522f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o	if (ctx) {
523f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o		if (ctx->blocksize) {
524f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o			ret_sb = ctx->blocksize * 8;
525f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o			if (ctx->blocksize == 1024)
526f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o				ret_sb++;
527f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o			ctx->superblock = ret_sb;
528f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o			return ret_sb;
529f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o		}
530f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o		ctx->superblock = ret_sb;
531f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o		ctx->blocksize = 1024;
532f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o	}
533f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o
534f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o	if (!name || !manager)
535f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o		goto cleanup;
536f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o
537f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o	if (manager->open(name, 0, &io) != 0)
538f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o		goto cleanup;
539f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o
540f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o	if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
541f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o		goto cleanup;
542f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o	sb = (struct ext2_super_block *) buf;
543f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o
544932a489cdf6bc83d69e59d3f8e0a57b733799ce1Andreas Dilger	for (blocksize = EXT2_MIN_BLOCK_SIZE;
545932a489cdf6bc83d69e59d3f8e0a57b733799ce1Andreas Dilger	     blocksize <= EXT2_MAX_BLOCK_SIZE ; blocksize *= 2) {
546f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o		superblock = blocksize*8;
547f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o		if (blocksize == 1024)
548f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o			superblock++;
549f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o		io_channel_set_blksize(io, blocksize);
550e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		if (io_channel_read_blk64(io, superblock,
551f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o					-SUPERBLOCK_SIZE, buf))
552f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o			continue;
5532eae093081a097a0a611fe2817e1533825dfdd86Theodore Ts'o#ifdef WORDS_BIGENDIAN
554f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o		if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
555f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o			ext2fs_swap_super(sb);
556f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o#endif
557e7b5d3c0b2bb1bafc5be57796ac1b68b1ac8e983Daniel Drake		if ((sb->s_magic == EXT2_SUPER_MAGIC) &&
558e7b5d3c0b2bb1bafc5be57796ac1b68b1ac8e983Daniel Drake		    (EXT2_BLOCK_SIZE(sb) == blocksize)) {
559557ddb2fdf46c055d80c66267c8c83299527c8d1Theodore Ts'o			ret_sb = superblock;
560557ddb2fdf46c055d80c66267c8c83299527c8d1Theodore Ts'o			if (ctx) {
561557ddb2fdf46c055d80c66267c8c83299527c8d1Theodore Ts'o				ctx->superblock = superblock;
562557ddb2fdf46c055d80c66267c8c83299527c8d1Theodore Ts'o				ctx->blocksize = blocksize;
563557ddb2fdf46c055d80c66267c8c83299527c8d1Theodore Ts'o			}
564f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o			break;
565f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o		}
566f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o	}
567f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o
568f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'ocleanup:
569f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o	if (io)
570f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o		io_channel_close(io);
571f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o	if (buf)
572f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o		ext2fs_free_mem(&buf);
573f1a1761d678a5ac539419f62676ce4c1bbd0767eTheodore Ts'o	return (ret_sb);
5741b6bf1759af884957234b7dce768b785f792abd0Theodore Ts'o}
5753839e65723771b85975f4263102dd3ceec4523cTheodore Ts'o
5766fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o/*
5776fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o * Given a mode, return the ext2 file type
5786fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o */
5796fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'oint ext2_file_type(unsigned int mode)
5806fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o{
5816fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o	if (LINUX_S_ISREG(mode))
5826fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o		return EXT2_FT_REG_FILE;
5836fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o
5846fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o	if (LINUX_S_ISDIR(mode))
5856fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o		return EXT2_FT_DIR;
586efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
5876fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o	if (LINUX_S_ISCHR(mode))
5886fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o		return EXT2_FT_CHRDEV;
589efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
5906fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o	if (LINUX_S_ISBLK(mode))
5916fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o		return EXT2_FT_BLKDEV;
592efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
5936fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o	if (LINUX_S_ISLNK(mode))
5946fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o		return EXT2_FT_SYMLINK;
5956fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o
5966fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o	if (LINUX_S_ISFIFO(mode))
5976fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o		return EXT2_FT_FIFO;
598efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
5996fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o	if (LINUX_S_ISSOCK(mode))
6006fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o		return EXT2_FT_SOCK;
601efc6f628e15de95bcd13e4f0ee223cb42115d520Theodore Ts'o
6026fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o	return 0;
6036fdc7a325c8bff67fc3a0489d0858bc7c48dc1a3Theodore Ts'o}
60449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos
60549a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos#define STRIDE_LENGTH 8
60649a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos/*
60749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos * Helper function which zeros out _num_ blocks starting at _blk_.  In
60849a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos * case of an error, the details of the error is returned via _ret_blk_
60949a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos * and _ret_count_ if they are non-NULL pointers.  Returns 0 on
61049a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos * success, and an error code on an error.
61149a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos *
61249a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos * As a special case, if the first argument is NULL, then it will
61349a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos * attempt to free the static zeroizing buffer.  (This is to keep
61449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos * programs that check for memory leaks happy.)
61549a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos */
61649a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santoserrcode_t e2fsck_zero_blocks(ext2_filsys fs, blk_t blk, int num,
61749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			     blk_t *ret_blk, int *ret_count)
61849a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos{
619e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	int		j, count;
62049a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos	static char	*buf;
62149a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos	errcode_t	retval;
62249a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos
62349a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos	/* If fs is null, clean up the static buffer and return */
62449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos	if (!fs) {
62549a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		if (buf) {
62649a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			free(buf);
62749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			buf = 0;
62849a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		}
62949a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		return 0;
63049a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos	}
63149a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos	/* Allocate the zeroizing buffer if necessary */
63249a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos	if (!buf) {
63349a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		buf = malloc(fs->blocksize * STRIDE_LENGTH);
63449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		if (!buf) {
635e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			com_err("malloc", ENOMEM, "%s",
63649a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos				_("while allocating zeroizing buffer"));
63749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			exit(1);
63849a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		}
63949a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		memset(buf, 0, fs->blocksize * STRIDE_LENGTH);
64049a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos	}
64149a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos	/* OK, do the write loop */
64249a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos	for (j = 0; j < num; j += STRIDE_LENGTH, blk += STRIDE_LENGTH) {
64349a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		count = num - j;
64449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		if (count > STRIDE_LENGTH)
64549a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			count = STRIDE_LENGTH;
646e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		retval = io_channel_write_blk64(fs->io, blk, count, buf);
64749a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		if (retval) {
64849a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			if (ret_count)
64949a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos				*ret_count = count;
65049a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			if (ret_blk)
65149a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos				*ret_blk = blk;
65249a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos			return retval;
65349a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos		}
65449a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos	}
65549a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos	return 0;
65649a7360ba6b986242d9f0f33e102291d2e0dfb47Jose R. Santos}
65780875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o
65880875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o/*
65980875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o * Check to see if a filesystem is in /proc/filesystems.
66080875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o * Returns 1 if found, 0 if not
66180875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o */
66280875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'oint fs_proc_check(const char *fs_name)
66380875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o{
66480875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	FILE	*f;
66580875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	char	buf[80], *cp, *t;
66680875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o
66780875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	f = fopen("/proc/filesystems", "r");
66880875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	if (!f)
66980875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		return (0);
67080875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	while (!feof(f)) {
67180875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		if (!fgets(buf, sizeof(buf), f))
67280875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o			break;
67380875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		cp = buf;
67480875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		if (!isspace(*cp)) {
67580875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o			while (*cp && !isspace(*cp))
67680875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o				cp++;
67780875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		}
67880875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		while (*cp && isspace(*cp))
67980875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o			cp++;
68080875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		if ((t = strchr(cp, '\n')) != NULL)
68180875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o			*t = 0;
68280875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		if ((t = strchr(cp, '\t')) != NULL)
68380875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o			*t = 0;
68480875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		if ((t = strchr(cp, ' ')) != NULL)
68580875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o			*t = 0;
68680875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		if (!strcmp(fs_name, cp)) {
68780875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o			fclose(f);
68880875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o			return (1);
68980875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		}
69080875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	}
69180875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	fclose(f);
69280875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	return (0);
69380875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o}
69480875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o
69580875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o/*
69680875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o * Check to see if a filesystem is available as a module
69780875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o * Returns 1 if found, 0 if not
69880875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o */
69980875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'oint check_for_modules(const char *fs_name)
70080875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o{
70180875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o#ifdef __linux__
70280875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	struct utsname	uts;
70380875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	FILE		*f;
70480875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	char		buf[1024], *cp, *t;
70580875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	int		i;
70680875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o
70780875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	if (uname(&uts))
70880875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		return (0);
70980875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	snprintf(buf, sizeof(buf), "/lib/modules/%s/modules.dep", uts.release);
71080875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o
71180875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	f = fopen(buf, "r");
71280875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	if (!f)
71380875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		return (0);
71480875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	while (!feof(f)) {
71580875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		if (!fgets(buf, sizeof(buf), f))
71680875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o			break;
71780875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		if ((cp = strchr(buf, ':')) != NULL)
71880875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o			*cp = 0;
71980875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		else
72080875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o			continue;
72180875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		if ((cp = strrchr(buf, '/')) != NULL)
72280875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o			cp++;
723f2fe5da31deebc689bb64e71c8e873efc925d312Eric Sandeen		else
724f2fe5da31deebc689bb64e71c8e873efc925d312Eric Sandeen			cp = buf;
72580875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		i = strlen(cp);
72680875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		if (i > 3) {
72780875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o			t = cp + i - 3;
72880875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o			if (!strcmp(t, ".ko"))
72980875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o				*t = 0;
73080875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		}
73180875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		if (!strcmp(cp, fs_name)) {
73280875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o			fclose(f);
73380875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o			return (1);
73480875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o		}
73580875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	}
73680875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	fclose(f);
73780875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o#endif /* __linux__ */
73880875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o	return (0);
73980875db58a6db58e3e2f01caf1adabca068d3ffbTheodore Ts'o}
740b0258cbcd89862b927707258c67f2eeac769adc2Theodore Ts'o
741b0258cbcd89862b927707258c67f2eeac769adc2Theodore Ts'o/*
742b0258cbcd89862b927707258c67f2eeac769adc2Theodore Ts'o * Helper function that does the right thing if write returns a
743b0258cbcd89862b927707258c67f2eeac769adc2Theodore Ts'o * partial write, or an EGAIN/EINTR error.
744b0258cbcd89862b927707258c67f2eeac769adc2Theodore Ts'o */
745b0258cbcd89862b927707258c67f2eeac769adc2Theodore Ts'oint write_all(int fd, char *buf, size_t count)
746b0258cbcd89862b927707258c67f2eeac769adc2Theodore Ts'o{
747b0258cbcd89862b927707258c67f2eeac769adc2Theodore Ts'o	ssize_t ret;
748b0258cbcd89862b927707258c67f2eeac769adc2Theodore Ts'o	int c = 0;
749b0258cbcd89862b927707258c67f2eeac769adc2Theodore Ts'o
750b0258cbcd89862b927707258c67f2eeac769adc2Theodore Ts'o	while (count > 0) {
751b0258cbcd89862b927707258c67f2eeac769adc2Theodore Ts'o		ret = write(fd, buf, count);
752b0258cbcd89862b927707258c67f2eeac769adc2Theodore Ts'o		if (ret < 0) {
753b0258cbcd89862b927707258c67f2eeac769adc2Theodore Ts'o			if ((errno == EAGAIN) || (errno == EINTR))
754b0258cbcd89862b927707258c67f2eeac769adc2Theodore Ts'o				continue;
755b0258cbcd89862b927707258c67f2eeac769adc2Theodore Ts'o			return -1;
756b0258cbcd89862b927707258c67f2eeac769adc2Theodore Ts'o		}
757b0258cbcd89862b927707258c67f2eeac769adc2Theodore Ts'o		count -= ret;
758b0258cbcd89862b927707258c67f2eeac769adc2Theodore Ts'o		buf += ret;
759b0258cbcd89862b927707258c67f2eeac769adc2Theodore Ts'o		c += ret;
760b0258cbcd89862b927707258c67f2eeac769adc2Theodore Ts'o	}
761b0258cbcd89862b927707258c67f2eeac769adc2Theodore Ts'o	return c;
762b0258cbcd89862b927707258c67f2eeac769adc2Theodore Ts'o}
763e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
764e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallvoid dump_mmp_msg(struct mmp_struct *mmp, const char *msg)
765e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{
766e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
767e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (msg)
768e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		printf("MMP check failed: %s\n", msg);
769e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (mmp) {
770e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		time_t t = mmp->mmp_time;
771e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
772e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		printf("MMP error info: last update: %s node: %s device: %s\n",
773e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		       ctime(&t), mmp->mmp_nodename, mmp->mmp_bdevname);
774e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	}
775e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}
776e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
777e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t e2fsck_mmp_update(ext2_filsys fs)
778e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{
779e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	errcode_t retval;
780e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
781e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	retval = ext2fs_mmp_update(fs);
782e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (retval == EXT2_ET_MMP_CHANGE_ABORT)
783e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		dump_mmp_msg(fs->mmp_cmp,
784e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			     _("UNEXPECTED INCONSISTENCY: the filesystem is "
785e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			       "being modified while fsck is running.\n"));
786e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
787e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	return retval;
788e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}
789e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
790e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallvoid e2fsck_set_bitmap_type(ext2_filsys fs, unsigned int default_type,
791e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			    const char *profile_name, unsigned int *old_type)
792e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{
793e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	unsigned type;
794e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
795e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	if (old_type)
796e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall		*old_type = fs->default_bitmap_type;
797e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#ifdef HAVE_SIGNAL_H
798e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	profile_get_uint(e2fsck_global_ctx->profile, "bitmaps",
799e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			 profile_name, 0, default_type, &type);
800e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	profile_get_uint(e2fsck_global_ctx->profile, "bitmaps",
801e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall			 "all", 0, type, &type);
802e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	fs->default_bitmap_type = type ? type : default_type;
803e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#else
804e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	fs->default_bitmap_type = default_type;
805e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall#endif
806e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}
807e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
808e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t e2fsck_allocate_inode_bitmap(ext2_filsys fs, const char *descr,
809e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				       int deftype,
810e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				       const char *name,
811e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				       ext2fs_inode_bitmap *ret)
812e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{
813e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	errcode_t	retval;
814e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	unsigned int	save_type;
815e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
816e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	e2fsck_set_bitmap_type(fs, deftype, name, &save_type);
817e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	retval = ext2fs_allocate_inode_bitmap(fs, descr, ret);
818e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	fs->default_bitmap_type = save_type;
819e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	return retval;
820e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}
821e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
822e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t e2fsck_allocate_block_bitmap(ext2_filsys fs, const char *descr,
823e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				       int deftype,
824e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				       const char *name,
825e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall				       ext2fs_block_bitmap *ret)
826e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{
827e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	errcode_t	retval;
828e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	unsigned int	save_type;
829e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
830e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	e2fsck_set_bitmap_type(fs, deftype, name, &save_type);
831e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	retval = ext2fs_allocate_block_bitmap(fs, descr, ret);
832e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	fs->default_bitmap_type = save_type;
833e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	return retval;
834e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}
835e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
836e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrallerrcode_t e2fsck_allocate_subcluster_bitmap(ext2_filsys fs, const char *descr,
837e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					    int deftype,
838e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					    const char *name,
839e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall					    ext2fs_block_bitmap *ret)
840e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall{
841e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	errcode_t	retval;
842e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	unsigned int	save_type;
843e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall
844e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	e2fsck_set_bitmap_type(fs, deftype, name, &save_type);
845e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	retval = ext2fs_allocate_subcluster_bitmap(fs, descr, ret);
846e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	fs->default_bitmap_type = save_type;
847e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall	return retval;
848e0ed7404719a9ddd2ba427a80db5365c8bad18c0JP Abgrall}
849