util.c revision 4dbfd79d1458ce1259b951377e341aeb6197f8c1
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, _("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, _("yes\n")); 239 else 240 log_out(ctx, _("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 int 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 int 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 466extern void e2fsck_write_inode_full(e2fsck_t ctx, unsigned long ino, 467 struct ext2_inode * inode, int bufsize, 468 const char *proc) 469{ 470 int 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 480extern void e2fsck_write_inode(e2fsck_t ctx, unsigned long ino, 481 struct ext2_inode * inode, const char *proc) 482{ 483 int 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, 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 796 if (old_type) 797 *old_type = fs->default_bitmap_type; 798 profile_get_uint(e2fsck_global_ctx->profile, "bitmaps", 799 profile_name, 0, default_type, &type); 800 profile_get_uint(e2fsck_global_ctx->profile, "bitmaps", 801 "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} 846