]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blame_incremental - e2fsck/util.c
fix cross-compilation support
[thirdparty/e2fsprogs.git] / e2fsck / util.c
... / ...
CommitLineData
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 "config.h"
13#include <stdlib.h>
14#include <stdio.h>
15#include <unistd.h>
16#include <string.h>
17#include <ctype.h>
18#ifdef __linux__
19#include <sys/utsname.h>
20#endif
21
22#ifdef HAVE_CONIO_H
23#undef HAVE_TERMIOS_H
24#include <conio.h>
25#define read_a_char() getch()
26#else
27#ifdef HAVE_TERMIOS_H
28#include <termios.h>
29#endif
30#endif
31
32#ifdef HAVE_MALLOC_H
33#include <malloc.h>
34#endif
35
36#ifdef HAVE_ERRNO_H
37#include <errno.h>
38#endif
39
40#include "e2fsck.h"
41
42extern e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
43
44#include <stdarg.h>
45#include <time.h>
46#include <sys/time.h>
47#include <sys/resource.h>
48
49void fatal_error(e2fsck_t ctx, const char *msg)
50{
51 ext2_filsys fs = ctx->fs;
52 int exit_value = FSCK_ERROR;
53
54 if (msg)
55 fprintf (stderr, "e2fsck: %s\n", msg);
56 if (!fs)
57 goto out;
58 if (fs->io && fs->super) {
59 ext2fs_mmp_stop(ctx->fs);
60 if (ctx->fs->io->magic == EXT2_ET_MAGIC_IO_CHANNEL)
61 io_channel_flush(ctx->fs->io);
62 else
63 log_err(ctx, "e2fsck: io manager magic bad!\n");
64 }
65 if (ext2fs_test_changed(fs)) {
66 exit_value |= FSCK_NONDESTRUCT;
67 log_out(ctx, _("\n%s: ***** FILE SYSTEM WAS MODIFIED *****\n"),
68 ctx->device_name);
69 if (ctx->mount_flags & EXT2_MF_ISROOT)
70 exit_value |= FSCK_REBOOT;
71 }
72 if (!ext2fs_test_valid(fs)) {
73 log_out(ctx, _("\n%s: ********** WARNING: Filesystem still has "
74 "errors **********\n\n"), ctx->device_name);
75 exit_value |= FSCK_UNCORRECTED;
76 exit_value &= ~FSCK_NONDESTRUCT;
77 }
78out:
79 ctx->flags |= E2F_FLAG_ABORT;
80 if (ctx->flags & E2F_FLAG_SETJMP_OK)
81 longjmp(ctx->abort_loc, 1);
82 exit(exit_value);
83}
84
85void log_out(e2fsck_t ctx, const char *fmt, ...)
86{
87 va_list pvar;
88
89 va_start(pvar, fmt);
90 vprintf(fmt, pvar);
91 va_end(pvar);
92 if (ctx->logf) {
93 va_start(pvar, fmt);
94 vfprintf(ctx->logf, fmt, pvar);
95 va_end(pvar);
96 }
97}
98
99void log_err(e2fsck_t ctx, const char *fmt, ...)
100{
101 va_list pvar;
102
103 va_start(pvar, fmt);
104 vfprintf(stderr, fmt, pvar);
105 va_end(pvar);
106 if (ctx->logf) {
107 va_start(pvar, fmt);
108 vfprintf(ctx->logf, fmt, pvar);
109 va_end(pvar);
110 }
111}
112
113void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned int size,
114 const char *description)
115{
116 void *ret;
117 char buf[256];
118
119#ifdef DEBUG_ALLOCATE_MEMORY
120 printf("Allocating %u bytes for %s...\n", size, description);
121#endif
122 ret = malloc(size);
123 if (!ret) {
124 sprintf(buf, "Can't allocate %u bytes for %s\n",
125 size, description);
126 fatal_error(ctx, buf);
127 }
128 memset(ret, 0, size);
129 return ret;
130}
131
132char *string_copy(e2fsck_t ctx EXT2FS_ATTR((unused)),
133 const char *str, int len)
134{
135 char *ret;
136
137 if (!str)
138 return NULL;
139 if (!len)
140 len = strlen(str);
141 ret = malloc(len+1);
142 if (ret) {
143 strncpy(ret, str, len);
144 ret[len] = 0;
145 }
146 return ret;
147}
148
149#ifndef HAVE_STRNLEN
150/*
151 * Incredibly, libc5 doesn't appear to have strnlen. So we have to
152 * provide our own.
153 */
154int e2fsck_strnlen(const char * s, int count)
155{
156 const char *cp = s;
157
158 while (count-- && *cp)
159 cp++;
160 return cp - s;
161}
162#endif
163
164#ifndef HAVE_CONIO_H
165static int read_a_char(void)
166{
167 char c;
168 int r;
169 int fail = 0;
170
171 while(1) {
172 if (e2fsck_global_ctx &&
173 (e2fsck_global_ctx->flags & E2F_FLAG_CANCEL)) {
174 return 3;
175 }
176 r = read(0, &c, 1);
177 if (r == 1)
178 return c;
179 if (fail++ > 100)
180 break;
181 }
182 return EOF;
183}
184#endif
185
186int ask_yn(e2fsck_t ctx, const char * string, int def)
187{
188 int c;
189 const char *defstr;
190 const char *short_yes = _("yY");
191 const char *short_no = _("nN");
192
193#ifdef HAVE_TERMIOS_H
194 struct termios termios, tmp;
195
196 tcgetattr (0, &termios);
197 tmp = termios;
198 tmp.c_lflag &= ~(ICANON | ECHO);
199 tmp.c_cc[VMIN] = 1;
200 tmp.c_cc[VTIME] = 0;
201 tcsetattr (0, TCSANOW, &tmp);
202#endif
203
204 if (def == 1)
205 defstr = _(_("<y>"));
206 else if (def == 0)
207 defstr = _(_("<n>"));
208 else
209 defstr = _(" (y/n)");
210 log_out(ctx, "%s%s? ", string, defstr);
211 while (1) {
212 fflush (stdout);
213 if ((c = read_a_char()) == EOF)
214 break;
215 if (c == 3) {
216#ifdef HAVE_TERMIOS_H
217 tcsetattr (0, TCSANOW, &termios);
218#endif
219 if (ctx->flags & E2F_FLAG_SETJMP_OK) {
220 log_out(ctx, "\n");
221 longjmp(e2fsck_global_ctx->abort_loc, 1);
222 }
223 log_out(ctx, "%s", _("cancelled!\n"));
224 return 0;
225 }
226 if (strchr(short_yes, (char) c)) {
227 def = 1;
228 break;
229 }
230 else if (strchr(short_no, (char) c)) {
231 def = 0;
232 break;
233 }
234 else if ((c == 27 || c == ' ' || c == '\n') && (def != -1))
235 break;
236 }
237 if (def)
238 log_out(ctx, "%s", _("yes\n"));
239 else
240 log_out(ctx, "%s", _("no\n"));
241#ifdef HAVE_TERMIOS_H
242 tcsetattr (0, TCSANOW, &termios);
243#endif
244 return def;
245}
246
247int ask (e2fsck_t ctx, const char * string, int def)
248{
249 if (ctx->options & E2F_OPT_NO) {
250 log_out(ctx, _("%s? no\n\n"), string);
251 return 0;
252 }
253 if (ctx->options & E2F_OPT_YES) {
254 log_out(ctx, _("%s? yes\n\n"), string);
255 return 1;
256 }
257 if (ctx->options & E2F_OPT_PREEN) {
258 log_out(ctx, "%s? %s\n\n", string, def ? _("yes") : _("no"));
259 return def;
260 }
261 return ask_yn(ctx, string, def);
262}
263
264void e2fsck_read_bitmaps(e2fsck_t ctx)
265{
266 ext2_filsys fs = ctx->fs;
267 errcode_t retval;
268 const char *old_op;
269 unsigned int save_type;
270
271 if (ctx->invalid_bitmaps) {
272 com_err(ctx->program_name, 0,
273 _("e2fsck_read_bitmaps: illegal bitmap block(s) for %s"),
274 ctx->device_name);
275 fatal_error(ctx, 0);
276 }
277
278 old_op = ehandler_operation(_("reading inode and block bitmaps"));
279 e2fsck_set_bitmap_type(fs, EXT2FS_BMAP64_RBTREE, "fs_bitmaps",
280 &save_type);
281 retval = ext2fs_read_bitmaps(fs);
282 fs->default_bitmap_type = save_type;
283 ehandler_operation(old_op);
284 if (retval) {
285 com_err(ctx->program_name, retval,
286 _("while retrying to read bitmaps for %s"),
287 ctx->device_name);
288 fatal_error(ctx, 0);
289 }
290}
291
292void e2fsck_write_bitmaps(e2fsck_t ctx)
293{
294 ext2_filsys fs = ctx->fs;
295 errcode_t retval;
296 const char *old_op;
297
298 old_op = ehandler_operation(_("writing block and inode bitmaps"));
299 retval = ext2fs_write_bitmaps(fs);
300 ehandler_operation(old_op);
301 if (retval) {
302 com_err(ctx->program_name, retval,
303 _("while rewriting block and inode bitmaps for %s"),
304 ctx->device_name);
305 fatal_error(ctx, 0);
306 }
307}
308
309void preenhalt(e2fsck_t ctx)
310{
311 ext2_filsys fs = ctx->fs;
312
313 if (!(ctx->options & E2F_OPT_PREEN))
314 return;
315 log_err(ctx, _("\n\n%s: UNEXPECTED INCONSISTENCY; "
316 "RUN fsck MANUALLY.\n\t(i.e., without -a or -p options)\n"),
317 ctx->device_name);
318 ctx->flags |= E2F_FLAG_EXITING;
319 if (fs != NULL) {
320 fs->super->s_state |= EXT2_ERROR_FS;
321 ext2fs_mark_super_dirty(fs);
322 ext2fs_close(fs);
323 }
324 exit(FSCK_UNCORRECTED);
325}
326
327#ifdef RESOURCE_TRACK
328void init_resource_track(struct resource_track *track, io_channel channel)
329{
330#ifdef HAVE_GETRUSAGE
331 struct rusage r;
332#endif
333 io_stats io_start = 0;
334
335 track->brk_start = sbrk(0);
336 gettimeofday(&track->time_start, 0);
337#ifdef HAVE_GETRUSAGE
338#ifdef sun
339 memset(&r, 0, sizeof(struct rusage));
340#endif
341 getrusage(RUSAGE_SELF, &r);
342 track->user_start = r.ru_utime;
343 track->system_start = r.ru_stime;
344#else
345 track->user_start.tv_sec = track->user_start.tv_usec = 0;
346 track->system_start.tv_sec = track->system_start.tv_usec = 0;
347#endif
348 track->bytes_read = 0;
349 track->bytes_written = 0;
350 if (channel && channel->manager && channel->manager->get_stats)
351 channel->manager->get_stats(channel, &io_start);
352 if (io_start) {
353 track->bytes_read = io_start->bytes_read;
354 track->bytes_written = io_start->bytes_written;
355 }
356}
357
358#ifdef __GNUC__
359#define _INLINE_ __inline__
360#else
361#define _INLINE_
362#endif
363
364static _INLINE_ float timeval_subtract(struct timeval *tv1,
365 struct timeval *tv2)
366{
367 return ((tv1->tv_sec - tv2->tv_sec) +
368 ((float) (tv1->tv_usec - tv2->tv_usec)) / 1000000);
369}
370
371void print_resource_track(e2fsck_t ctx, const char *desc,
372 struct resource_track *track, io_channel channel)
373{
374#ifdef HAVE_GETRUSAGE
375 struct rusage r;
376#endif
377#ifdef HAVE_MALLINFO
378 struct mallinfo malloc_info;
379#endif
380 struct timeval time_end;
381
382 if ((desc && !(ctx->options & E2F_OPT_TIME2)) ||
383 (!desc && !(ctx->options & E2F_OPT_TIME)))
384 return;
385
386 e2fsck_clear_progbar(ctx);
387 gettimeofday(&time_end, 0);
388
389 if (desc)
390 log_out(ctx, "%s: ", desc);
391
392#ifdef HAVE_MALLINFO
393#define kbytes(x) (((unsigned long)(x) + 1023) / 1024)
394
395 malloc_info = mallinfo();
396 log_out(ctx, _("Memory used: %luk/%luk (%luk/%luk), "),
397 kbytes(malloc_info.arena), kbytes(malloc_info.hblkhd),
398 kbytes(malloc_info.uordblks), kbytes(malloc_info.fordblks));
399#else
400 log_out(ctx, _("Memory used: %lu, "),
401 (unsigned long) (((char *) sbrk(0)) -
402 ((char *) track->brk_start)));
403#endif
404#ifdef HAVE_GETRUSAGE
405 getrusage(RUSAGE_SELF, &r);
406
407 log_out(ctx, _("time: %5.2f/%5.2f/%5.2f\n"),
408 timeval_subtract(&time_end, &track->time_start),
409 timeval_subtract(&r.ru_utime, &track->user_start),
410 timeval_subtract(&r.ru_stime, &track->system_start));
411#else
412 log_out(ctx, _("elapsed time: %6.3f\n"),
413 timeval_subtract(&time_end, &track->time_start));
414#endif
415#define mbytes(x) (((x) + 1048575) / 1048576)
416 if (channel && channel->manager && channel->manager->get_stats) {
417 io_stats delta = 0;
418 unsigned long long bytes_read = 0;
419 unsigned long long bytes_written = 0;
420
421 if (desc)
422 log_out(ctx, "%s: ", desc);
423
424 channel->manager->get_stats(channel, &delta);
425 if (delta) {
426 bytes_read = delta->bytes_read - track->bytes_read;
427 bytes_written = delta->bytes_written -
428 track->bytes_written;
429 }
430 log_out(ctx, "I/O read: %lluMB, write: %lluMB, "
431 "rate: %.2fMB/s\n",
432 mbytes(bytes_read), mbytes(bytes_written),
433 (double)mbytes(bytes_read + bytes_written) /
434 timeval_subtract(&time_end, &track->time_start));
435 }
436}
437#endif /* RESOURCE_TRACK */
438
439void e2fsck_read_inode(e2fsck_t ctx, unsigned long ino,
440 struct ext2_inode * inode, const char *proc)
441{
442 errcode_t retval;
443
444 retval = ext2fs_read_inode(ctx->fs, ino, inode);
445 if (retval) {
446 com_err("ext2fs_read_inode", retval,
447 _("while reading inode %lu in %s"), ino, proc);
448 fatal_error(ctx, 0);
449 }
450}
451
452void e2fsck_read_inode_full(e2fsck_t ctx, unsigned long ino,
453 struct ext2_inode *inode, int bufsize,
454 const char *proc)
455{
456 errcode_t retval;
457
458 retval = ext2fs_read_inode_full(ctx->fs, ino, inode, bufsize);
459 if (retval) {
460 com_err("ext2fs_read_inode_full", retval,
461 _("while reading inode %lu in %s"), ino, proc);
462 fatal_error(ctx, 0);
463 }
464}
465
466void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino,
467 struct ext2_inode * inode, int bufsize,
468 const char *proc)
469{
470 errcode_t retval;
471
472 retval = ext2fs_write_inode_full(ctx->fs, ino, inode, bufsize);
473 if (retval) {
474 com_err("ext2fs_write_inode", retval,
475 _("while writing inode %lu in %s"), ino, proc);
476 fatal_error(ctx, 0);
477 }
478}
479
480void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino,
481 struct ext2_inode * inode, const char *proc)
482{
483 errcode_t retval;
484
485 retval = ext2fs_write_inode(ctx->fs, ino, inode);
486 if (retval) {
487 com_err("ext2fs_write_inode", retval,
488 _("while writing inode %lu in %s"), ino, proc);
489 fatal_error(ctx, 0);
490 }
491}
492
493#ifdef MTRACE
494void mtrace_print(char *mesg)
495{
496 FILE *malloc_get_mallstream();
497 FILE *f = malloc_get_mallstream();
498
499 if (f)
500 fprintf(f, "============= %s\n", mesg);
501}
502#endif
503
504blk64_t get_backup_sb(e2fsck_t ctx, ext2_filsys fs, const char *name,
505 io_manager manager)
506{
507 struct ext2_super_block *sb;
508 io_channel io = NULL;
509 void *buf = NULL;
510 int blocksize;
511 blk64_t superblock, ret_sb = 8193;
512
513 if (fs && fs->super) {
514 ret_sb = (fs->super->s_blocks_per_group +
515 fs->super->s_first_data_block);
516 if (ctx) {
517 ctx->superblock = ret_sb;
518 ctx->blocksize = fs->blocksize;
519 }
520 return ret_sb;
521 }
522
523 if (ctx) {
524 if (ctx->blocksize) {
525 ret_sb = ctx->blocksize * 8;
526 if (ctx->blocksize == 1024)
527 ret_sb++;
528 ctx->superblock = ret_sb;
529 return ret_sb;
530 }
531 ctx->superblock = ret_sb;
532 ctx->blocksize = 1024;
533 }
534
535 if (!name || !manager)
536 goto cleanup;
537
538 if (manager->open(name, 0, &io) != 0)
539 goto cleanup;
540
541 if (ext2fs_get_mem(SUPERBLOCK_SIZE, &buf))
542 goto cleanup;
543 sb = (struct ext2_super_block *) buf;
544
545 for (blocksize = EXT2_MIN_BLOCK_SIZE;
546 blocksize <= EXT2_MAX_BLOCK_SIZE ; blocksize *= 2) {
547 superblock = blocksize*8;
548 if (blocksize == 1024)
549 superblock++;
550 io_channel_set_blksize(io, blocksize);
551 if (io_channel_read_blk64(io, superblock,
552 -SUPERBLOCK_SIZE, buf))
553 continue;
554#ifdef WORDS_BIGENDIAN
555 if (sb->s_magic == ext2fs_swab16(EXT2_SUPER_MAGIC))
556 ext2fs_swap_super(sb);
557#endif
558 if ((sb->s_magic == EXT2_SUPER_MAGIC) &&
559 (EXT2_BLOCK_SIZE(sb) == blocksize)) {
560 ret_sb = superblock;
561 if (ctx) {
562 ctx->superblock = superblock;
563 ctx->blocksize = blocksize;
564 }
565 break;
566 }
567 }
568
569cleanup:
570 if (io)
571 io_channel_close(io);
572 if (buf)
573 ext2fs_free_mem(&buf);
574 return (ret_sb);
575}
576
577/*
578 * Given a mode, return the ext2 file type
579 */
580int ext2_file_type(unsigned int mode)
581{
582 if (LINUX_S_ISREG(mode))
583 return EXT2_FT_REG_FILE;
584
585 if (LINUX_S_ISDIR(mode))
586 return EXT2_FT_DIR;
587
588 if (LINUX_S_ISCHR(mode))
589 return EXT2_FT_CHRDEV;
590
591 if (LINUX_S_ISBLK(mode))
592 return EXT2_FT_BLKDEV;
593
594 if (LINUX_S_ISLNK(mode))
595 return EXT2_FT_SYMLINK;
596
597 if (LINUX_S_ISFIFO(mode))
598 return EXT2_FT_FIFO;
599
600 if (LINUX_S_ISSOCK(mode))
601 return EXT2_FT_SOCK;
602
603 return 0;
604}
605
606#define STRIDE_LENGTH 8
607/*
608 * Helper function which zeros out _num_ blocks starting at _blk_. In
609 * case of an error, the details of the error is returned via _ret_blk_
610 * and _ret_count_ if they are non-NULL pointers. Returns 0 on
611 * success, and an error code on an error.
612 *
613 * As a special case, if the first argument is NULL, then it will
614 * attempt to free the static zeroizing buffer. (This is to keep
615 * programs that check for memory leaks happy.)
616 */
617errcode_t e2fsck_zero_blocks(ext2_filsys fs, blk_t blk, int num,
618 blk_t *ret_blk, int *ret_count)
619{
620 int j, count;
621 static char *buf;
622 errcode_t retval;
623
624 /* If fs is null, clean up the static buffer and return */
625 if (!fs) {
626 if (buf) {
627 free(buf);
628 buf = 0;
629 }
630 return 0;
631 }
632 /* Allocate the zeroizing buffer if necessary */
633 if (!buf) {
634 buf = malloc(fs->blocksize * STRIDE_LENGTH);
635 if (!buf) {
636 com_err("malloc", ENOMEM, "%s",
637 _("while allocating zeroizing buffer"));
638 exit(1);
639 }
640 memset(buf, 0, fs->blocksize * STRIDE_LENGTH);
641 }
642 /* OK, do the write loop */
643 for (j = 0; j < num; j += STRIDE_LENGTH, blk += STRIDE_LENGTH) {
644 count = num - j;
645 if (count > STRIDE_LENGTH)
646 count = STRIDE_LENGTH;
647 retval = io_channel_write_blk64(fs->io, blk, count, buf);
648 if (retval) {
649 if (ret_count)
650 *ret_count = count;
651 if (ret_blk)
652 *ret_blk = blk;
653 return retval;
654 }
655 }
656 return 0;
657}
658
659/*
660 * Check to see if a filesystem is in /proc/filesystems.
661 * Returns 1 if found, 0 if not
662 */
663int fs_proc_check(const char *fs_name)
664{
665 FILE *f;
666 char buf[80], *cp, *t;
667
668 f = fopen("/proc/filesystems", "r");
669 if (!f)
670 return (0);
671 while (!feof(f)) {
672 if (!fgets(buf, sizeof(buf), f))
673 break;
674 cp = buf;
675 if (!isspace(*cp)) {
676 while (*cp && !isspace(*cp))
677 cp++;
678 }
679 while (*cp && isspace(*cp))
680 cp++;
681 if ((t = strchr(cp, '\n')) != NULL)
682 *t = 0;
683 if ((t = strchr(cp, '\t')) != NULL)
684 *t = 0;
685 if ((t = strchr(cp, ' ')) != NULL)
686 *t = 0;
687 if (!strcmp(fs_name, cp)) {
688 fclose(f);
689 return (1);
690 }
691 }
692 fclose(f);
693 return (0);
694}
695
696/*
697 * Check to see if a filesystem is available as a module
698 * Returns 1 if found, 0 if not
699 */
700int check_for_modules(const char *fs_name)
701{
702#ifdef __linux__
703 struct utsname uts;
704 FILE *f;
705 char buf[1024], *cp, *t;
706 int i;
707
708 if (uname(&uts))
709 return (0);
710 snprintf(buf, sizeof(buf), "/lib/modules/%s/modules.dep", uts.release);
711
712 f = fopen(buf, "r");
713 if (!f)
714 return (0);
715 while (!feof(f)) {
716 if (!fgets(buf, sizeof(buf), f))
717 break;
718 if ((cp = strchr(buf, ':')) != NULL)
719 *cp = 0;
720 else
721 continue;
722 if ((cp = strrchr(buf, '/')) != NULL)
723 cp++;
724 else
725 cp = buf;
726 i = strlen(cp);
727 if (i > 3) {
728 t = cp + i - 3;
729 if (!strcmp(t, ".ko"))
730 *t = 0;
731 }
732 if (!strcmp(cp, fs_name)) {
733 fclose(f);
734 return (1);
735 }
736 }
737 fclose(f);
738#endif /* __linux__ */
739 return (0);
740}
741
742/*
743 * Helper function that does the right thing if write returns a
744 * partial write, or an EGAIN/EINTR error.
745 */
746int write_all(int fd, char *buf, size_t count)
747{
748 ssize_t ret;
749 int c = 0;
750
751 while (count > 0) {
752 ret = write(fd, buf, count);
753 if (ret < 0) {
754 if ((errno == EAGAIN) || (errno == EINTR))
755 continue;
756 return -1;
757 }
758 count -= ret;
759 buf += ret;
760 c += ret;
761 }
762 return c;
763}
764
765void dump_mmp_msg(struct mmp_struct *mmp, const char *msg)
766{
767
768 if (msg)
769 printf("MMP check failed: %s\n", msg);
770 if (mmp) {
771 time_t t = mmp->mmp_time;
772
773 printf("MMP error info: last update: %s node: %s device: %s\n",
774 ctime(&t), mmp->mmp_nodename, mmp->mmp_bdevname);
775 }
776}
777
778errcode_t e2fsck_mmp_update(ext2_filsys fs)
779{
780 errcode_t retval;
781
782 retval = ext2fs_mmp_update(fs);
783 if (retval == EXT2_ET_MMP_CHANGE_ABORT)
784 dump_mmp_msg(fs->mmp_cmp,
785 _("UNEXPECTED INCONSISTENCY: the filesystem is "
786 "being modified while fsck is running.\n"));
787
788 return retval;
789}
790
791void e2fsck_set_bitmap_type(ext2_filsys fs, unsigned int default_type,
792 const char *profile_name, unsigned int *old_type)
793{
794 unsigned type;
795 e2fsck_t ctx = (e2fsck_t) fs->priv_data;
796
797 if (old_type)
798 *old_type = fs->default_bitmap_type;
799 profile_get_uint(ctx->profile, "bitmaps", profile_name, 0,
800 default_type, &type);
801 profile_get_uint(ctx->profile, "bitmaps", "all", 0, type, &type);
802 fs->default_bitmap_type = type ? type : default_type;
803}
804
805errcode_t e2fsck_allocate_inode_bitmap(ext2_filsys fs, const char *descr,
806 int deftype,
807 const char *name,
808 ext2fs_inode_bitmap *ret)
809{
810 errcode_t retval;
811 unsigned int save_type;
812
813 e2fsck_set_bitmap_type(fs, deftype, name, &save_type);
814 retval = ext2fs_allocate_inode_bitmap(fs, descr, ret);
815 fs->default_bitmap_type = save_type;
816 return retval;
817}
818
819errcode_t e2fsck_allocate_block_bitmap(ext2_filsys fs, const char *descr,
820 int deftype,
821 const char *name,
822 ext2fs_block_bitmap *ret)
823{
824 errcode_t retval;
825 unsigned int save_type;
826
827 e2fsck_set_bitmap_type(fs, deftype, name, &save_type);
828 retval = ext2fs_allocate_block_bitmap(fs, descr, ret);
829 fs->default_bitmap_type = save_type;
830 return retval;
831}
832
833errcode_t e2fsck_allocate_subcluster_bitmap(ext2_filsys fs, const char *descr,
834 int deftype,
835 const char *name,
836 ext2fs_block_bitmap *ret)
837{
838 errcode_t retval;
839 unsigned int save_type;
840
841 e2fsck_set_bitmap_type(fs, deftype, name, &save_type);
842 retval = ext2fs_allocate_subcluster_bitmap(fs, descr, ret);
843 fs->default_bitmap_type = save_type;
844 return retval;
845}