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