diff options
Diffstat (limited to 'e2fsprogs/e2fsck/util.c')
-rw-r--r-- | e2fsprogs/e2fsck/util.c | 503 |
1 files changed, 0 insertions, 503 deletions
diff --git a/e2fsprogs/e2fsck/util.c b/e2fsprogs/e2fsck/util.c deleted file mode 100644 index 311156e23..000000000 --- a/e2fsprogs/e2fsck/util.c +++ /dev/null | |||
@@ -1,503 +0,0 @@ | |||
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 | |||
17 | #ifdef HAVE_CONIO_H | ||
18 | #undef HAVE_TERMIOS_H | ||
19 | #include <conio.h> | ||
20 | #define read_a_char() getch() | ||
21 | #else | ||
22 | #ifdef HAVE_TERMIOS_H | ||
23 | #include <termios.h> | ||
24 | #endif | ||
25 | #include <stdio.h> | ||
26 | #endif | ||
27 | |||
28 | #ifdef HAVE_MALLOC_H | ||
29 | #include <malloc.h> | ||
30 | #endif | ||
31 | |||
32 | #include "e2fsck.h" | ||
33 | |||
34 | extern e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */ | ||
35 | |||
36 | #include <sys/time.h> | ||
37 | #include <sys/resource.h> | ||
38 | |||
39 | #if 0 | ||
40 | void fatal_error(e2fsck_t ctx, const char *msg) | ||
41 | { | ||
42 | if (msg) | ||
43 | fprintf (stderr, "e2fsck: %s\n", msg); | ||
44 | if (ctx->fs && ctx->fs->io) { | ||
45 | if (ctx->fs->io->magic == EXT2_ET_MAGIC_IO_CHANNEL) | ||
46 | io_channel_flush(ctx->fs->io); | ||
47 | else | ||
48 | fprintf(stderr, "e2fsck: io manager magic bad!\n"); | ||
49 | } | ||
50 | ctx->flags |= E2F_FLAG_ABORT; | ||
51 | if (ctx->flags & E2F_FLAG_SETJMP_OK) | ||
52 | longjmp(ctx->abort_loc, 1); | ||
53 | exit(FSCK_ERROR); | ||
54 | } | ||
55 | #endif | ||
56 | |||
57 | void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size, | ||
58 | const char *description) | ||
59 | { | ||
60 | void *ret; | ||
61 | char buf[256]; | ||
62 | |||
63 | #ifdef DEBUG_ALLOCATE_MEMORY | ||
64 | printf("Allocating %d bytes for %s...\n", size, description); | ||
65 | #endif | ||
66 | ret = malloc(size); | ||
67 | if (!ret) { | ||
68 | sprintf(buf, "Can't allocate %s\n", description); | ||
69 | fatal_error(ctx, buf); | ||
70 | } | ||
71 | memset(ret, 0, size); | ||
72 | return ret; | ||
73 | } | ||
74 | |||
75 | char *string_copy(e2fsck_t ctx EXT2FS_ATTR((unused)), | ||
76 | const char *str, int len) | ||
77 | { | ||
78 | char *ret; | ||
79 | |||
80 | if (!str) | ||
81 | return NULL; | ||
82 | if (!len) | ||
83 | len = strlen(str); | ||
84 | ret = malloc(len+1); | ||
85 | if (ret) { | ||
86 | strncpy(ret, str, len); | ||
87 | ret[len] = 0; | ||
88 | } | ||
89 | return ret; | ||
90 | } | ||
91 | |||
92 | #ifndef HAVE_STRNLEN | ||
93 | /* | ||
94 | * Incredibly, libc5 doesn't appear to have strnlen. So we have to | ||
95 | * provide our own. | ||
96 | */ | ||
97 | int e2fsck_strnlen(const char * s, int count) | ||
98 | { | ||
99 | const char *cp = s; | ||
100 | |||
101 | while (count-- && *cp) | ||
102 | cp++; | ||
103 | return cp - s; | ||
104 | } | ||
105 | #endif | ||
106 | |||
107 | #ifndef HAVE_CONIO_H | ||
108 | static int read_a_char(void) | ||
109 | { | ||
110 | char c; | ||
111 | int r; | ||
112 | int fail = 0; | ||
113 | |||
114 | while(1) { | ||
115 | if (e2fsck_global_ctx && | ||
116 | (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) { | ||
117 | return 3; | ||
118 | } | ||
119 | r = read(0, &c, 1); | ||
120 | if (r == 1) | ||
121 | return c; | ||
122 | if (fail++ > 100) | ||
123 | break; | ||
124 | } | ||
125 | return EOF; | ||
126 | } | ||
127 | #endif | ||
128 | |||
129 | int ask_yn(const char * string, int def) | ||
130 | { | ||
131 | int c; | ||
132 | const char *defstr; | ||
133 | const char *short_yes = _("yY"); | ||
134 | const char *short_no = _("nN"); | ||
135 | |||
136 | #ifdef HAVE_TERMIOS_H | ||
137 | struct termios termios, tmp; | ||
138 | |||
139 | tcgetattr (0, &termios); | ||
140 | tmp = termios; | ||
141 | tmp.c_lflag &= ~(ICANON | ECHO); | ||
142 | tmp.c_cc[VMIN] = 1; | ||
143 | tmp.c_cc[VTIME] = 0; | ||
144 | tcsetattr (0, TCSANOW, &tmp); | ||
145 | #endif | ||
146 | |||
147 | if (def == 1) | ||
148 | defstr = _(_("<y>")); | ||
149 | else if (def == 0) | ||
150 | defstr = _(_("<n>")); | ||
151 | else | ||
152 | defstr = _(" (y/n)"); | ||
153 | printf("%s%s? ", string, defstr); | ||
154 | while (1) { | ||
155 | fflush (stdout); | ||
156 | if ((c = read_a_char()) == EOF) | ||
157 | break; | ||
158 | if (c == 3) { | ||
159 | #ifdef HAVE_TERMIOS_H | ||
160 | tcsetattr (0, TCSANOW, &termios); | ||
161 | #endif | ||
162 | if (e2fsck_global_ctx && | ||
163 | e2fsck_global_ctx->flags & E2F_FLAG_SETJMP_OK) { | ||
164 | puts("\n"); | ||
165 | longjmp(e2fsck_global_ctx->abort_loc, 1); | ||
166 | } | ||
167 | puts(_("cancelled!\n")); | ||
168 | return 0; | ||
169 | } | ||
170 | if (strchr(short_yes, (char) c)) { | ||
171 | def = 1; | ||
172 | break; | ||
173 | } | ||
174 | else if (strchr(short_no, (char) c)) { | ||
175 | def = 0; | ||
176 | break; | ||
177 | } | ||
178 | else if ((c == ' ' || c == '\n') && (def != -1)) | ||
179 | break; | ||
180 | } | ||
181 | if (def) | ||
182 | puts(_("yes\n")); | ||
183 | else | ||
184 | puts (_("no\n")); | ||
185 | #ifdef HAVE_TERMIOS_H | ||
186 | tcsetattr (0, TCSANOW, &termios); | ||
187 | #endif | ||
188 | return def; | ||
189 | } | ||
190 | |||
191 | int ask (e2fsck_t ctx, const char * string, int def) | ||
192 | { | ||
193 | if (ctx->options & E2F_OPT_NO) { | ||
194 | printf (_("%s? no\n\n"), string); | ||
195 | return 0; | ||
196 | } | ||
197 | if (ctx->options & E2F_OPT_YES) { | ||
198 | printf (_("%s? yes\n\n"), string); | ||
199 | return 1; | ||
200 | } | ||
201 | if (ctx->options & E2F_OPT_PREEN) { | ||
202 | printf ("%s? %s\n\n", string, def ? _("yes") : _("no")); | ||
203 | return def; | ||
204 | } | ||
205 | return ask_yn(string, def); | ||
206 | } | ||
207 | |||
208 | void e2fsck_read_bitmaps(e2fsck_t ctx) | ||
209 | { | ||
210 | ext2_filsys fs = ctx->fs; | ||
211 | errcode_t retval; | ||
212 | |||
213 | if (ctx->invalid_bitmaps) { | ||
214 | com_err(ctx->program_name, 0, | ||
215 | _("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"), | ||
216 | ctx->device_name); | ||
217 | fatal_error(ctx, 0); | ||
218 | } | ||
219 | |||
220 | ehandler_operation(_("reading inode and block bitmaps")); | ||
221 | retval = ext2fs_read_bitmaps(fs); | ||
222 | ehandler_operation(0); | ||
223 | if (retval) { | ||
224 | com_err(ctx->program_name, retval, | ||
225 | _("while retrying to read bitmaps for %s"), | ||
226 | ctx->device_name); | ||
227 | fatal_error(ctx, 0); | ||
228 | } | ||
229 | } | ||
230 | |||
231 | void e2fsck_write_bitmaps(e2fsck_t ctx) | ||
232 | { | ||
233 | ext2_filsys fs = ctx->fs; | ||
234 | errcode_t retval; | ||
235 | |||
236 | if (ext2fs_test_bb_dirty(fs)) { | ||
237 | ehandler_operation(_("writing block bitmaps")); | ||
238 | retval = ext2fs_write_block_bitmap(fs); | ||
239 | ehandler_operation(0); | ||
240 | if (retval) { | ||
241 | com_err(ctx->program_name, retval, | ||
242 | _("while retrying to write block bitmaps for %s"), | ||
243 | ctx->device_name); | ||
244 | fatal_error(ctx, 0); | ||
245 | } | ||
246 | } | ||
247 | |||
248 | if (ext2fs_test_ib_dirty(fs)) { | ||
249 | ehandler_operation(_("writing inode bitmaps")); | ||
250 | retval = ext2fs_write_inode_bitmap(fs); | ||
251 | ehandler_operation(0); | ||
252 | if (retval) { | ||
253 | com_err(ctx->program_name, retval, | ||
254 | _("while retrying to write inode bitmaps for %s"), | ||
255 | ctx->device_name); | ||
256 | fatal_error(ctx, 0); | ||
257 | } | ||
258 | } | ||
259 | } | ||
260 | |||
261 | void preenhalt(e2fsck_t ctx) | ||
262 | { | ||
263 | ext2_filsys fs = ctx->fs; | ||
264 | |||
265 | if (!(ctx->options & E2F_OPT_PREEN)) | ||
266 | return; | ||
267 | fprintf(stderr, _("\n\n%s: UNEXPECTED INCONSISTENCY; " | ||
268 | "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"), | ||
269 | ctx->device_name); | ||
270 | if (fs != NULL) { | ||
271 | fs->super->s_state |= EXT2_ERROR_FS; | ||
272 | ext2fs_mark_super_dirty(fs); | ||
273 | ext2fs_close(fs); | ||
274 | } | ||
275 | exit(FSCK_UNCORRECTED); | ||
276 | } | ||
277 | |||
278 | #ifdef RESOURCE_TRACK | ||
279 | void init_resource_track(struct resource_track *track) | ||
280 | { | ||
281 | #ifdef HAVE_GETRUSAGE | ||
282 | struct rusage r; | ||
283 | #endif | ||
284 | |||
285 | track->brk_start = sbrk(0); | ||
286 | gettimeofday(&track->time_start, 0); | ||
287 | #ifdef HAVE_GETRUSAGE | ||
288 | #ifdef sun | ||
289 | memset(&r, 0, sizeof(struct rusage)); | ||
290 | #endif | ||
291 | getrusage(RUSAGE_SELF, &r); | ||
292 | track->user_start = r.ru_utime; | ||
293 | track->system_start = r.ru_stime; | ||
294 | #else | ||
295 | track->user_start.tv_sec = track->user_start.tv_usec = 0; | ||
296 | track->system_start.tv_sec = track->system_start.tv_usec = 0; | ||
297 | #endif | ||
298 | } | ||
299 | |||
300 | #ifdef __GNUC__ | ||
301 | #define _INLINE_ __inline__ | ||
302 | #else | ||
303 | #define _INLINE_ | ||
304 | #endif | ||
305 | |||
306 | static _INLINE_ float timeval_subtract(struct timeval *tv1, | ||
307 | struct timeval *tv2) | ||
308 | { | ||
309 | return ((tv1->tv_sec - tv2->tv_sec) + | ||
310 | ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000); | ||
311 | } | ||
312 | |||
313 | void print_resource_track(const char *desc, struct resource_track *track) | ||
314 | { | ||
315 | #ifdef HAVE_GETRUSAGE | ||
316 | struct rusage r; | ||
317 | #endif | ||
318 | #ifdef HAVE_MALLINFO | ||
319 | struct mallinfo malloc_info; | ||
320 | #endif | ||
321 | struct timeval time_end; | ||
322 | |||
323 | gettimeofday(&time_end, 0); | ||
324 | |||
325 | if (desc) | ||
326 | printf("%s: ", desc); | ||
327 | |||
328 | #ifdef HAVE_MALLINFO | ||
329 | #define kbytes(x) (((x) + 1023) / 1024) | ||
330 | |||
331 | malloc_info = mallinfo(); | ||
332 | printf(_("Memory used: %dk/%dk (%dk/%dk), "), | ||
333 | kbytes(malloc_info.arena), kbytes(malloc_info.hblkhd), | ||
334 | kbytes(malloc_info.uordblks), kbytes(malloc_info.fordblks)); | ||
335 | #else | ||
336 | printf(_("Memory used: %d, "), | ||
337 | (int) (((char *) sbrk(0)) - ((char *) track->brk_start))); | ||
338 | #endif | ||
339 | #ifdef HAVE_GETRUSAGE | ||
340 | getrusage(RUSAGE_SELF, &r); | ||
341 | |||
342 | printf(_("time: %5.2f/%5.2f/%5.2f\n"), | ||
343 | timeval_subtract(&time_end, &track->time_start), | ||
344 | timeval_subtract(&r.ru_utime, &track->user_start), | ||
345 | timeval_subtract(&r.ru_stime, &track->system_start)); | ||
346 | #else | ||
347 | printf(_("elapsed time: %6.3f\n"), | ||
348 | timeval_subtract(&time_end, &track->time_start)); | ||
349 | #endif | ||
350 | } | ||
351 | #endif /* RESOURCE_TRACK */ | ||
352 | |||
353 | void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino, | ||
354 | struct ext2_inode * inode, const char *proc) | ||
355 | { | ||
356 | int retval; | ||
357 | |||
358 | retval = ext2fs_read_inode(ctx->fs, ino, inode); | ||
359 | if (retval) { | ||
360 | com_err("ext2fs_read_inode", retval, | ||
361 | _("while reading inode %ld in %s"), ino, proc); | ||
362 | fatal_error(ctx, 0); | ||
363 | } | ||
364 | } | ||
365 | |||
366 | extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino, | ||
367 | struct ext2_inode * inode, int bufsize, | ||
368 | const char *proc) | ||
369 | { | ||
370 | int retval; | ||
371 | |||
372 | retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize); | ||
373 | if (retval) { | ||
374 | com_err("ext2fs_write_inode", retval, | ||
375 | _("while writing inode %ld in %s"), ino, proc); | ||
376 | fatal_error(ctx, 0); | ||
377 | } | ||
378 | } | ||
379 | |||
380 | extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino, | ||
381 | struct ext2_inode * inode, const char *proc) | ||
382 | { | ||
383 | int retval; | ||
384 | |||
385 | retval = ext2fs_write_inode(ctx->fs, ino, inode); | ||
386 | if (retval) { | ||
387 | com_err("ext2fs_write_inode", retval, | ||
388 | _("while writing inode %ld in %s"), ino, proc); | ||
389 | fatal_error(ctx, 0); | ||
390 | } | ||
391 | } | ||
392 | |||
393 | #ifdef MTRACE | ||
394 | void mtrace_print(char *mesg) | ||
395 | { | ||
396 | FILE *malloc_get_mallstream(); | ||
397 | FILE *f = malloc_get_mallstream(); | ||
398 | |||
399 | if (f) | ||
400 | fprintf(f, "============= %s\n", mesg); | ||
401 | } | ||
402 | #endif | ||
403 | |||
404 | blk_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name, | ||
405 | io_manager manager) | ||
406 | { | ||
407 | struct ext2_super_block *sb; | ||
408 | io_channel io = NULL; | ||
409 | void *buf = NULL; | ||
410 | int blocksize; | ||
411 | blk_t superblock, ret_sb = 8193; | ||
412 | |||
413 | if (fs && fs->super) { | ||
414 | ret_sb = (fs->super->s_blocks_per_group + | ||
415 | fs->super->s_first_data_block); | ||
416 | if (ctx) { | ||
417 | ctx->superblock = ret_sb; | ||
418 | ctx->blocksize = fs->blocksize; | ||
419 | } | ||
420 | return ret_sb; | ||
421 | } | ||
422 | |||
423 | if (ctx) { | ||
424 | if (ctx->blocksize) { | ||
425 | ret_sb = ctx->blocksize * 8; | ||
426 | if (ctx->blocksize == 1024) | ||
427 | ret_sb++; | ||
428 | ctx->superblock = ret_sb; | ||
429 | return ret_sb; | ||
430 | } | ||
431 | ctx->superblock = ret_sb; | ||
432 | ctx->blocksize = 1024; | ||
433 | } | ||
434 | |||
435 | if (!name || !manager) | ||
436 | goto cleanup; | ||
437 | |||
438 | if (manager->open(name, 0, &io) != 0) | ||
439 | goto cleanup; | ||
440 | |||
441 | if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf)) | ||
442 | goto cleanup; | ||
443 | sb = (struct ext2_super_block *) buf; | ||
444 | |||
445 | for (blocksize = EXT2_MIN_BLOCK_SIZE; | ||
446 | blocksize <= EXT2_MAX_BLOCK_SIZE ; blocksize *= 2) { | ||
447 | superblock = blocksize*8; | ||
448 | if (blocksize == 1024) | ||
449 | superblock++; | ||
450 | io_channel_set_blksize(io, blocksize); | ||
451 | if (io_channel_read_blk(io, superblock, | ||
452 | -SUPERBLOCK_SIZE, buf)) | ||
453 | continue; | ||
454 | #ifdef EXT2FS_ENABLE_SWAPFS | ||
455 | if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC)) | ||
456 | ext2fs_swap_super(sb); | ||
457 | #endif | ||
458 | if (sb->s_magic == EXT2_SUPER_MAGIC) { | ||
459 | ret_sb = superblock; | ||
460 | if (ctx) { | ||
461 | ctx->superblock = superblock; | ||
462 | ctx->blocksize = blocksize; | ||
463 | } | ||
464 | break; | ||
465 | } | ||
466 | } | ||
467 | |||
468 | cleanup: | ||
469 | if (io) | ||
470 | io_channel_close(io); | ||
471 | if (buf) | ||
472 | ext2fs_free_mem(&buf); | ||
473 | return (ret_sb); | ||
474 | } | ||
475 | |||
476 | /* | ||
477 | * Given a mode, return the ext2 file type | ||
478 | */ | ||
479 | int ext2_file_type(unsigned int mode) | ||
480 | { | ||
481 | if (LINUX_S_ISREG(mode)) | ||
482 | return EXT2_FT_REG_FILE; | ||
483 | |||
484 | if (LINUX_S_ISDIR(mode)) | ||
485 | return EXT2_FT_DIR; | ||
486 | |||
487 | if (LINUX_S_ISCHR(mode)) | ||
488 | return EXT2_FT_CHRDEV; | ||
489 | |||
490 | if (LINUX_S_ISBLK(mode)) | ||
491 | return EXT2_FT_BLKDEV; | ||
492 | |||
493 | if (LINUX_S_ISLNK(mode)) | ||
494 | return EXT2_FT_SYMLINK; | ||
495 | |||
496 | if (LINUX_S_ISFIFO(mode)) | ||
497 | return EXT2_FT_FIFO; | ||
498 | |||
499 | if (LINUX_S_ISSOCK(mode)) | ||
500 | return EXT2_FT_SOCK; | ||
501 | |||
502 | return 0; | ||
503 | } | ||