]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blob - e2fsck/util.c
Many files:
[thirdparty/e2fsprogs.git] / e2fsck / util.c
1 /*
2 * util.c --- miscellaneous utilities
3 *
4 * Copyright (C) 1993, 1994, 1995, 1996, 1997 Theodore Ts'o.
5 *
6 * %Begin-Header%
7 * This file may be redistributed under the terms of the GNU Public
8 * License.
9 * %End-Header%
10 */
11
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include <string.h>
15 #include <ctype.h>
16 #include <termios.h>
17
18 #include "e2fsck.h"
19
20 #include <sys/time.h>
21 #include <sys/resource.h>
22
23 void fatal_error (const char *msg)
24 {
25 if (msg)
26 fprintf (stderr, "e2fsck: %s\n", msg);
27 exit(FSCK_ERROR);
28 }
29
30 void *allocate_memory(int size, const char *description)
31 {
32 void *ret;
33 char buf[256];
34
35 #ifdef DEBUG_ALLOCATE_MEMORY
36 printf("Allocating %d bytes for %s...\n", size, description);
37 #endif
38 ret = malloc(size);
39 if (!ret) {
40 sprintf(buf, "Can't allocate %s\n", description);
41 fatal_error(buf);
42 }
43 memset(ret, 0, size);
44 return ret;
45 }
46
47 int ask_yn(const char * string, int def)
48 {
49 int c;
50 struct termios termios, tmp;
51 const char *defstr;
52
53 tcgetattr (0, &termios);
54 tmp = termios;
55 tmp.c_lflag &= ~(ICANON | ECHO);
56 tmp.c_cc[VMIN] = 1;
57 tmp.c_cc[VTIME] = 0;
58 tcsetattr (0, TCSANOW, &tmp);
59
60 if (def == 1)
61 defstr = "<y>";
62 else if (def == 0)
63 defstr = "<n>";
64 else
65 defstr = " (y/n)";
66 printf("%s%s? ", string, defstr);
67 while (1) {
68 fflush (stdout);
69 if ((c = getchar()) == EOF)
70 break;
71 c = toupper(c);
72 if (c == 'Y') {
73 def = 1;
74 break;
75 }
76 else if (c == 'N') {
77 def = 0;
78 break;
79 }
80 else if ((c == ' ' || c == '\n') && (def != -1))
81 break;
82 }
83 if (def)
84 printf ("yes\n\n");
85 else
86 printf ("no\n\n");
87 tcsetattr (0, TCSANOW, &termios);
88 return def;
89 }
90
91 int ask (e2fsck_t ctx, const char * string, int def)
92 {
93 if (ctx->options & E2F_OPT_NO) {
94 printf ("%s? no\n\n", string);
95 return 0;
96 }
97 if (ctx->options & E2F_OPT_YES) {
98 printf ("%s? yes\n\n", string);
99 return 1;
100 }
101 if (ctx->options & E2F_OPT_PREEN) {
102 printf ("%s? %s\n\n", string, def ? "yes" : "no");
103 return def;
104 }
105 return ask_yn(string, def);
106 }
107
108 void read_bitmaps(e2fsck_t ctx)
109 {
110 ext2_filsys fs = ctx->fs;
111 errcode_t retval;
112
113 if (ctx->invalid_bitmaps) {
114 com_err(ctx->program_name, 0,
115 "read_bitmaps: illegal bitmap block(s) for %s",
116 ctx->device_name);
117 fatal_error(0);
118 }
119
120 ehandler_operation("reading inode and block bitmaps");
121 retval = ext2fs_read_bitmaps(fs);
122 ehandler_operation(0);
123 if (retval) {
124 com_err(ctx->program_name, retval,
125 "while retrying to read bitmaps for %s",
126 ctx->device_name);
127 fatal_error(0);
128 }
129 }
130
131 void write_bitmaps(e2fsck_t ctx)
132 {
133 ext2_filsys fs = ctx->fs;
134 errcode_t retval;
135
136 if (ext2fs_test_bb_dirty(fs)) {
137 ehandler_operation("writing block bitmaps");
138 retval = ext2fs_write_block_bitmap(fs);
139 ehandler_operation(0);
140 if (retval) {
141 com_err(ctx->program_name, retval,
142 "while retrying to write block bitmaps for %s",
143 ctx->device_name);
144 fatal_error(0);
145 }
146 }
147
148 if (ext2fs_test_ib_dirty(fs)) {
149 ehandler_operation("writing inode bitmaps");
150 retval = ext2fs_write_inode_bitmap(fs);
151 ehandler_operation(0);
152 if (retval) {
153 com_err(ctx->program_name, retval,
154 "while retrying to write inode bitmaps for %s",
155 ctx->device_name);
156 fatal_error(0);
157 }
158 }
159 }
160
161 void preenhalt(e2fsck_t ctx)
162 {
163 ext2_filsys fs = ctx->fs;
164
165 if (!(ctx->options & E2F_OPT_PREEN))
166 return;
167 fprintf(stderr, "\n\n%s: UNEXPECTED INCONSISTENCY; "
168 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n",
169 ctx->device_name);
170 if (fs != NULL) {
171 fs->super->s_state |= EXT2_ERROR_FS;
172 ext2fs_mark_super_dirty(fs);
173 ext2fs_close(fs);
174 }
175 exit(FSCK_UNCORRECTED);
176 }
177
178 void init_resource_track(struct resource_track *track)
179 {
180 #ifdef HAVE_GETRUSAGE
181 struct rusage r;
182 #endif
183
184 track->brk_start = sbrk(0);
185 gettimeofday(&track->time_start, 0);
186 #ifdef HAVE_GETRUSAGE
187 #ifdef solaris
188 memcpy(&r, 0, sizeof(struct rusage));
189 #endif
190 getrusage(RUSAGE_SELF, &r);
191 track->user_start = r.ru_utime;
192 track->system_start = r.ru_stime;
193 #else
194 track->user_start.tv_sec = track->user_start.tv_usec = 0;
195 track->system_start.tv_sec = track->system_start.tv_usec = 0;
196 #endif
197 }
198
199 #ifdef __GNUC__
200 #define _INLINE_ __inline__
201 #else
202 #define _INLINE_
203 #endif
204
205 static _INLINE_ float timeval_subtract(struct timeval *tv1,
206 struct timeval *tv2)
207 {
208 return ((tv1->tv_sec - tv2->tv_sec) +
209 ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
210 }
211
212 void print_resource_track(const char *desc, struct resource_track *track)
213 {
214 #ifdef HAVE_GETRUSAGE
215 struct rusage r;
216 #endif
217 struct timeval time_end;
218
219 gettimeofday(&time_end, 0);
220
221 if (desc)
222 printf("%s :", desc);
223
224 #ifdef HAVE_GETRUSAGE
225 getrusage(RUSAGE_SELF, &r);
226
227 printf("Memory used: %d, elapsed time: %6.3f/%6.3f/%6.3f\n",
228 (int) (((char *) sbrk(0)) - ((char *) track->brk_start)),
229 timeval_subtract(&time_end, &track->time_start),
230 timeval_subtract(&r.ru_utime, &track->user_start),
231 timeval_subtract(&r.ru_stime, &track->system_start));
232 #else
233 printf("Memory used: %d, elapsed time: %6.3f\n",
234 (int) (((char *) sbrk(0)) - ((char *) track->brk_start)),
235 timeval_subtract(&time_end, &track->time_start));
236 #endif
237 }
238
239 void e2fsck_read_inode(ext2_filsys fs, unsigned long ino,
240 struct ext2_inode * inode, const char *proc)
241 {
242 int retval;
243
244 retval = ext2fs_read_inode(fs, ino, inode);
245 if (retval) {
246 com_err("ext2fs_read_inode", retval,
247 "while reading inode %ld in %s", ino, proc);
248 fatal_error(0);
249 }
250 }
251
252 extern void e2fsck_write_inode(ext2_filsys fs, unsigned long ino,
253 struct ext2_inode * inode, const char *proc)
254 {
255 int retval;
256
257 retval = ext2fs_write_inode(fs, ino, inode);
258 if (retval) {
259 com_err("ext2fs_write_inode", retval,
260 "while writing inode %ld in %s", ino, proc);
261 fatal_error(0);
262 }
263 }
264
265 #ifdef MTRACE
266 void mtrace_print(char *mesg)
267 {
268 FILE *malloc_get_mallstream();
269 FILE *f = malloc_get_mallstream();
270
271 if (f)
272 fprintf(f, "============= %s\n", mesg);
273 }
274 #endif
275
276 blk_t get_backup_sb(ext2_filsys fs)
277 {
278 if (!fs || !fs->super)
279 return 8193;
280 return fs->super->s_blocks_per_group + 1;
281 }
282