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