diff options
Diffstat (limited to 'e2fsprogs/fsck.c')
-rw-r--r-- | e2fsprogs/fsck.c | 272 |
1 files changed, 144 insertions, 128 deletions
diff --git a/e2fsprogs/fsck.c b/e2fsprogs/fsck.c index d2d312e5c..627d2be31 100644 --- a/e2fsprogs/fsck.c +++ b/e2fsprogs/fsck.c | |||
@@ -33,9 +33,20 @@ | |||
33 | * spawns actual fsck.something for each filesystem to check. | 33 | * spawns actual fsck.something for each filesystem to check. |
34 | * It doesn't guess filesystem types from on-disk format. | 34 | * It doesn't guess filesystem types from on-disk format. |
35 | */ | 35 | */ |
36 | //config:config FSCK | ||
37 | //config: bool "fsck" | ||
38 | //config: default y | ||
39 | //config: help | ||
40 | //config: fsck is used to check and optionally repair one or more filesystems. | ||
41 | //config: In actuality, fsck is simply a front-end for the various file system | ||
42 | //config: checkers (fsck.fstype) available under Linux. | ||
43 | |||
44 | //applet:IF_FSCK(APPLET(fsck, BB_DIR_SBIN, BB_SUID_DROP)) | ||
45 | |||
46 | //kbuild:lib-$(CONFIG_FSCK) += fsck.o | ||
36 | 47 | ||
37 | //usage:#define fsck_trivial_usage | 48 | //usage:#define fsck_trivial_usage |
38 | //usage: "[-ANPRTV] [-C FD] [-t FSTYPE] [FS_OPTS] [BLOCKDEV]..." | 49 | //usage: "[-ANPRTV] [-t FSTYPE] [FS_OPTS] [BLOCKDEV]..." |
39 | //usage:#define fsck_full_usage "\n\n" | 50 | //usage:#define fsck_full_usage "\n\n" |
40 | //usage: "Check and repair filesystems\n" | 51 | //usage: "Check and repair filesystems\n" |
41 | //usage: "\n -A Walk /etc/fstab and check all filesystems" | 52 | //usage: "\n -A Walk /etc/fstab and check all filesystems" |
@@ -44,7 +55,8 @@ | |||
44 | //usage: "\n -R With -A, skip the root filesystem" | 55 | //usage: "\n -R With -A, skip the root filesystem" |
45 | //usage: "\n -T Don't show title on startup" | 56 | //usage: "\n -T Don't show title on startup" |
46 | //usage: "\n -V Verbose" | 57 | //usage: "\n -V Verbose" |
47 | //usage: "\n -C n Write status information to specified filedescriptor" | 58 | //DO_PROGRESS_INDICATOR is off: |
59 | ////usage: "\n -C FD Write status information to specified file descriptor" | ||
48 | //usage: "\n -t TYPE List of filesystem types to check" | 60 | //usage: "\n -t TYPE List of filesystem types to check" |
49 | 61 | ||
50 | #include "libbb.h" | 62 | #include "libbb.h" |
@@ -125,35 +137,42 @@ static const char really_wanted[] ALIGN1 = | |||
125 | 137 | ||
126 | #define BASE_MD "/dev/md" | 138 | #define BASE_MD "/dev/md" |
127 | 139 | ||
128 | static char **args; | 140 | struct globals { |
129 | static int num_args; | 141 | char **args; |
130 | static int verbose; | 142 | int num_args; |
143 | int verbose; | ||
131 | 144 | ||
132 | #define FS_TYPE_FLAG_NORMAL 0 | 145 | #define FS_TYPE_FLAG_NORMAL 0 |
133 | #define FS_TYPE_FLAG_OPT 1 | 146 | #define FS_TYPE_FLAG_OPT 1 |
134 | #define FS_TYPE_FLAG_NEGOPT 2 | 147 | #define FS_TYPE_FLAG_NEGOPT 2 |
135 | static char **fs_type_list; | 148 | char **fs_type_list; |
136 | static uint8_t *fs_type_flag; | 149 | uint8_t *fs_type_flag; |
137 | static smallint fs_type_negated; | 150 | smallint fs_type_negated; |
138 | 151 | ||
139 | static smallint noexecute; | 152 | smallint noexecute; |
140 | static smallint serialize; | 153 | smallint serialize; |
141 | static smallint skip_root; | 154 | smallint skip_root; |
142 | /* static smallint like_mount; */ | 155 | /* smallint like_mount; */ |
143 | static smallint parallel_root; | 156 | smallint parallel_root; |
144 | static smallint force_all_parallel; | 157 | smallint force_all_parallel; |
158 | smallint kill_sent; | ||
145 | 159 | ||
146 | #if DO_PROGRESS_INDICATOR | 160 | #if DO_PROGRESS_INDICATOR |
147 | static smallint progress; | 161 | smallint progress; |
148 | static int progress_fd; | 162 | int progress_fd; |
149 | #endif | 163 | #endif |
150 | 164 | ||
151 | static int num_running; | 165 | int num_running; |
152 | static int max_running; | 166 | int max_running; |
153 | static char *fstype; | 167 | char *fstype; |
154 | static struct fs_info *filesys_info; | 168 | struct fs_info *filesys_info; |
155 | static struct fs_info *filesys_last; | 169 | struct fs_info *filesys_last; |
156 | static struct fsck_instance *instance_list; | 170 | struct fsck_instance *instance_list; |
171 | } FIX_ALIASING; | ||
172 | #define G (*(struct globals*)&bb_common_bufsiz1) | ||
173 | #define INIT_G() do { \ | ||
174 | BUILD_BUG_ON(sizeof(G) > COMMON_BUFSIZE); \ | ||
175 | } while (0) | ||
157 | 176 | ||
158 | /* | 177 | /* |
159 | * Return the "base device" given a particular device; this is used to | 178 | * Return the "base device" given a particular device; this is used to |
@@ -302,11 +321,11 @@ static struct fs_info *create_fs_device(const char *device, const char *mntpnt, | |||
302 | /*fs->flags = 0; */ | 321 | /*fs->flags = 0; */ |
303 | /*fs->next = NULL; */ | 322 | /*fs->next = NULL; */ |
304 | 323 | ||
305 | if (!filesys_info) | 324 | if (!G.filesys_info) |
306 | filesys_info = fs; | 325 | G.filesys_info = fs; |
307 | else | 326 | else |
308 | filesys_last->next = fs; | 327 | G.filesys_last->next = fs; |
309 | filesys_last = fs; | 328 | G.filesys_last = fs; |
310 | 329 | ||
311 | return fs; | 330 | return fs; |
312 | } | 331 | } |
@@ -316,6 +335,7 @@ static void load_fs_info(const char *filename) | |||
316 | { | 335 | { |
317 | FILE *fstab; | 336 | FILE *fstab; |
318 | struct mntent mte; | 337 | struct mntent mte; |
338 | char buf[1024]; | ||
319 | 339 | ||
320 | fstab = setmntent(filename, "r"); | 340 | fstab = setmntent(filename, "r"); |
321 | if (!fstab) { | 341 | if (!fstab) { |
@@ -324,7 +344,7 @@ static void load_fs_info(const char *filename) | |||
324 | } | 344 | } |
325 | 345 | ||
326 | // Loop through entries | 346 | // Loop through entries |
327 | while (getmntent_r(fstab, &mte, bb_common_bufsiz1, COMMON_BUFSIZE)) { | 347 | while (getmntent_r(fstab, &mte, buf, sizeof(buf))) { |
328 | //bb_info_msg("CREATE[%s][%s][%s][%s][%d]", mte.mnt_fsname, mte.mnt_dir, | 348 | //bb_info_msg("CREATE[%s][%s][%s][%s][%d]", mte.mnt_fsname, mte.mnt_dir, |
329 | // mte.mnt_type, mte.mnt_opts, | 349 | // mte.mnt_type, mte.mnt_opts, |
330 | // mte.mnt_passno); | 350 | // mte.mnt_passno); |
@@ -340,7 +360,7 @@ static struct fs_info *lookup(char *filesys) | |||
340 | { | 360 | { |
341 | struct fs_info *fs; | 361 | struct fs_info *fs; |
342 | 362 | ||
343 | for (fs = filesys_info; fs; fs = fs->next) { | 363 | for (fs = G.filesys_info; fs; fs = fs->next) { |
344 | if (strcmp(filesys, fs->device) == 0 | 364 | if (strcmp(filesys, fs->device) == 0 |
345 | || (fs->mountpt && strcmp(filesys, fs->mountpt) == 0) | 365 | || (fs->mountpt && strcmp(filesys, fs->mountpt) == 0) |
346 | ) | 366 | ) |
@@ -355,7 +375,7 @@ static int progress_active(void) | |||
355 | { | 375 | { |
356 | struct fsck_instance *inst; | 376 | struct fsck_instance *inst; |
357 | 377 | ||
358 | for (inst = instance_list; inst; inst = inst->next) { | 378 | for (inst = G.instance_list; inst; inst = inst->next) { |
359 | if (inst->flags & FLAG_DONE) | 379 | if (inst->flags & FLAG_DONE) |
360 | continue; | 380 | continue; |
361 | if (inst->flags & FLAG_PROGRESS) | 381 | if (inst->flags & FLAG_PROGRESS) |
@@ -371,19 +391,17 @@ static int progress_active(void) | |||
371 | */ | 391 | */ |
372 | static void kill_all_if_got_signal(void) | 392 | static void kill_all_if_got_signal(void) |
373 | { | 393 | { |
374 | static smallint kill_sent; | ||
375 | |||
376 | struct fsck_instance *inst; | 394 | struct fsck_instance *inst; |
377 | 395 | ||
378 | if (!bb_got_signal || kill_sent) | 396 | if (!bb_got_signal || G.kill_sent) |
379 | return; | 397 | return; |
380 | 398 | ||
381 | for (inst = instance_list; inst; inst = inst->next) { | 399 | for (inst = G.instance_list; inst; inst = inst->next) { |
382 | if (inst->flags & FLAG_DONE) | 400 | if (inst->flags & FLAG_DONE) |
383 | continue; | 401 | continue; |
384 | kill(inst->pid, SIGTERM); | 402 | kill(inst->pid, SIGTERM); |
385 | } | 403 | } |
386 | kill_sent = 1; | 404 | G.kill_sent = 1; |
387 | } | 405 | } |
388 | 406 | ||
389 | /* | 407 | /* |
@@ -398,9 +416,9 @@ static int wait_one(int flags) | |||
398 | struct fsck_instance *inst, *prev; | 416 | struct fsck_instance *inst, *prev; |
399 | pid_t pid; | 417 | pid_t pid; |
400 | 418 | ||
401 | if (!instance_list) | 419 | if (!G.instance_list) |
402 | return -1; | 420 | return -1; |
403 | /* if (noexecute) { already returned -1; } */ | 421 | /* if (G.noexecute) { already returned -1; } */ |
404 | 422 | ||
405 | while (1) { | 423 | while (1) { |
406 | pid = waitpid(-1, &status, flags); | 424 | pid = waitpid(-1, &status, flags); |
@@ -418,7 +436,7 @@ static int wait_one(int flags) | |||
418 | continue; | 436 | continue; |
419 | } | 437 | } |
420 | prev = NULL; | 438 | prev = NULL; |
421 | inst = instance_list; | 439 | inst = G.instance_list; |
422 | do { | 440 | do { |
423 | if (inst->pid == pid) | 441 | if (inst->pid == pid) |
424 | goto child_died; | 442 | goto child_died; |
@@ -428,9 +446,8 @@ static int wait_one(int flags) | |||
428 | } | 446 | } |
429 | child_died: | 447 | child_died: |
430 | 448 | ||
431 | if (WIFEXITED(status)) | 449 | status = WEXITSTATUS(status); |
432 | status = WEXITSTATUS(status); | 450 | if (WIFSIGNALED(status)) { |
433 | else if (WIFSIGNALED(status)) { | ||
434 | sig = WTERMSIG(status); | 451 | sig = WTERMSIG(status); |
435 | status = EXIT_UNCORRECTED; | 452 | status = EXIT_UNCORRECTED; |
436 | if (sig != SIGINT) { | 453 | if (sig != SIGINT) { |
@@ -439,16 +456,12 @@ static int wait_one(int flags) | |||
439 | inst->prog, inst->device, sig); | 456 | inst->prog, inst->device, sig); |
440 | status = EXIT_ERROR; | 457 | status = EXIT_ERROR; |
441 | } | 458 | } |
442 | } else { | ||
443 | printf("%s %s: status is %x, should never happen\n", | ||
444 | inst->prog, inst->device, status); | ||
445 | status = EXIT_ERROR; | ||
446 | } | 459 | } |
447 | 460 | ||
448 | #if DO_PROGRESS_INDICATOR | 461 | #if DO_PROGRESS_INDICATOR |
449 | if (progress && (inst->flags & FLAG_PROGRESS) && !progress_active()) { | 462 | if (progress && (inst->flags & FLAG_PROGRESS) && !progress_active()) { |
450 | struct fsck_instance *inst2; | 463 | struct fsck_instance *inst2; |
451 | for (inst2 = instance_list; inst2; inst2 = inst2->next) { | 464 | for (inst2 = G.instance_list; inst2; inst2 = inst2->next) { |
452 | if (inst2->flags & FLAG_DONE) | 465 | if (inst2->flags & FLAG_DONE) |
453 | continue; | 466 | continue; |
454 | if (strcmp(inst2->type, "ext2") != 0 | 467 | if (strcmp(inst2->type, "ext2") != 0 |
@@ -475,11 +488,11 @@ static int wait_one(int flags) | |||
475 | if (prev) | 488 | if (prev) |
476 | prev->next = inst->next; | 489 | prev->next = inst->next; |
477 | else | 490 | else |
478 | instance_list = inst->next; | 491 | G.instance_list = inst->next; |
479 | if (verbose > 1) | 492 | if (G.verbose > 1) |
480 | printf("Finished with %s (exit status %d)\n", | 493 | printf("Finished with %s (exit status %d)\n", |
481 | inst->device, status); | 494 | inst->device, status); |
482 | num_running--; | 495 | G.num_running--; |
483 | free_instance(inst); | 496 | free_instance(inst); |
484 | 497 | ||
485 | return status; | 498 | return status; |
@@ -515,51 +528,51 @@ static void execute(const char *type, const char *device, | |||
515 | struct fsck_instance *inst; | 528 | struct fsck_instance *inst; |
516 | pid_t pid; | 529 | pid_t pid; |
517 | 530 | ||
518 | args[0] = xasprintf("fsck.%s", type); | 531 | G.args[0] = xasprintf("fsck.%s", type); |
519 | 532 | ||
520 | #if DO_PROGRESS_INDICATOR | 533 | #if DO_PROGRESS_INDICATOR |
521 | if (progress && !progress_active()) { | 534 | if (progress && !progress_active()) { |
522 | if (strcmp(type, "ext2") == 0 | 535 | if (strcmp(type, "ext2") == 0 |
523 | || strcmp(type, "ext3") == 0 | 536 | || strcmp(type, "ext3") == 0 |
524 | ) { | 537 | ) { |
525 | args[XXX] = xasprintf("-C%d", progress_fd); /* 1 */ | 538 | G.args[XXX] = xasprintf("-C%d", progress_fd); /* 1 */ |
526 | inst->flags |= FLAG_PROGRESS; | 539 | inst->flags |= FLAG_PROGRESS; |
527 | } | 540 | } |
528 | } | 541 | } |
529 | #endif | 542 | #endif |
530 | 543 | ||
531 | args[num_args - 2] = (char*)device; | 544 | G.args[G.num_args - 2] = (char*)device; |
532 | /* args[num_args - 1] = NULL; - already is */ | 545 | /* G.args[G.num_args - 1] = NULL; - already is */ |
533 | 546 | ||
534 | if (verbose || noexecute) { | 547 | if (G.verbose || G.noexecute) { |
535 | printf("[%s (%d) -- %s]", args[0], num_running, | 548 | printf("[%s (%d) -- %s]", G.args[0], G.num_running, |
536 | mntpt ? mntpt : device); | 549 | mntpt ? mntpt : device); |
537 | for (i = 0; args[i]; i++) | 550 | for (i = 0; G.args[i]; i++) |
538 | printf(" %s", args[i]); | 551 | printf(" %s", G.args[i]); |
539 | bb_putchar('\n'); | 552 | bb_putchar('\n'); |
540 | } | 553 | } |
541 | 554 | ||
542 | /* Fork and execute the correct program. */ | 555 | /* Fork and execute the correct program. */ |
543 | pid = -1; | 556 | pid = -1; |
544 | if (!noexecute) { | 557 | if (!G.noexecute) { |
545 | pid = spawn(args); | 558 | pid = spawn(G.args); |
546 | if (pid < 0) | 559 | if (pid < 0) |
547 | bb_simple_perror_msg(args[0]); | 560 | bb_simple_perror_msg(G.args[0]); |
548 | } | 561 | } |
549 | 562 | ||
550 | #if DO_PROGRESS_INDICATOR | 563 | #if DO_PROGRESS_INDICATOR |
551 | free(args[XXX]); | 564 | free(G.args[XXX]); |
552 | #endif | 565 | #endif |
553 | 566 | ||
554 | /* No child, so don't record an instance */ | 567 | /* No child, so don't record an instance */ |
555 | if (pid <= 0) { | 568 | if (pid <= 0) { |
556 | free(args[0]); | 569 | free(G.args[0]); |
557 | return; | 570 | return; |
558 | } | 571 | } |
559 | 572 | ||
560 | inst = xzalloc(sizeof(*inst)); | 573 | inst = xzalloc(sizeof(*inst)); |
561 | inst->pid = pid; | 574 | inst->pid = pid; |
562 | inst->prog = args[0]; | 575 | inst->prog = G.args[0]; |
563 | inst->device = xstrdup(device); | 576 | inst->device = xstrdup(device); |
564 | inst->base_device = base_device(device); | 577 | inst->base_device = base_device(device); |
565 | #if DO_PROGRESS_INDICATOR | 578 | #if DO_PROGRESS_INDICATOR |
@@ -568,8 +581,8 @@ static void execute(const char *type, const char *device, | |||
568 | 581 | ||
569 | /* Add to the list of running fsck's. | 582 | /* Add to the list of running fsck's. |
570 | * (was adding to the end, but adding to the front is simpler...) */ | 583 | * (was adding to the end, but adding to the front is simpler...) */ |
571 | inst->next = instance_list; | 584 | inst->next = G.instance_list; |
572 | instance_list = inst; | 585 | G.instance_list = inst; |
573 | } | 586 | } |
574 | 587 | ||
575 | /* | 588 | /* |
@@ -588,27 +601,27 @@ static void fsck_device(struct fs_info *fs /*, int interactive */) | |||
588 | 601 | ||
589 | if (strcmp(fs->type, "auto") != 0) { | 602 | if (strcmp(fs->type, "auto") != 0) { |
590 | type = fs->type; | 603 | type = fs->type; |
591 | if (verbose > 2) | 604 | if (G.verbose > 2) |
592 | bb_info_msg("using filesystem type '%s' %s", | 605 | bb_info_msg("using filesystem type '%s' %s", |
593 | type, "from fstab"); | 606 | type, "from fstab"); |
594 | } else if (fstype | 607 | } else if (G.fstype |
595 | && (fstype[0] != 'n' || fstype[1] != 'o') /* != "no" */ | 608 | && (G.fstype[0] != 'n' || G.fstype[1] != 'o') /* != "no" */ |
596 | && !is_prefixed_with(fstype, "opts=") | 609 | && !is_prefixed_with(G.fstype, "opts=") |
597 | && !is_prefixed_with(fstype, "loop") | 610 | && !is_prefixed_with(G.fstype, "loop") |
598 | && !strchr(fstype, ',') | 611 | && !strchr(G.fstype, ',') |
599 | ) { | 612 | ) { |
600 | type = fstype; | 613 | type = G.fstype; |
601 | if (verbose > 2) | 614 | if (G.verbose > 2) |
602 | bb_info_msg("using filesystem type '%s' %s", | 615 | bb_info_msg("using filesystem type '%s' %s", |
603 | type, "from -t"); | 616 | type, "from -t"); |
604 | } else { | 617 | } else { |
605 | type = "auto"; | 618 | type = "auto"; |
606 | if (verbose > 2) | 619 | if (G.verbose > 2) |
607 | bb_info_msg("using filesystem type '%s' %s", | 620 | bb_info_msg("using filesystem type '%s' %s", |
608 | type, "(default)"); | 621 | type, "(default)"); |
609 | } | 622 | } |
610 | 623 | ||
611 | num_running++; | 624 | G.num_running++; |
612 | execute(type, fs->device, fs->mountpt /*, interactive */); | 625 | execute(type, fs->device, fs->mountpt /*, interactive */); |
613 | } | 626 | } |
614 | 627 | ||
@@ -621,13 +634,13 @@ static int device_already_active(char *device) | |||
621 | struct fsck_instance *inst; | 634 | struct fsck_instance *inst; |
622 | char *base; | 635 | char *base; |
623 | 636 | ||
624 | if (force_all_parallel) | 637 | if (G.force_all_parallel) |
625 | return 0; | 638 | return 0; |
626 | 639 | ||
627 | #ifdef BASE_MD | 640 | #ifdef BASE_MD |
628 | /* Don't check a soft raid disk with any other disk */ | 641 | /* Don't check a soft raid disk with any other disk */ |
629 | if (instance_list | 642 | if (G.instance_list |
630 | && (is_prefixed_with(instance_list->device, BASE_MD) | 643 | && (is_prefixed_with(G.instance_list->device, BASE_MD) |
631 | || is_prefixed_with(device, BASE_MD)) | 644 | || is_prefixed_with(device, BASE_MD)) |
632 | ) { | 645 | ) { |
633 | return 1; | 646 | return 1; |
@@ -640,9 +653,9 @@ static int device_already_active(char *device) | |||
640 | * already active if there are any fsck instances running. | 653 | * already active if there are any fsck instances running. |
641 | */ | 654 | */ |
642 | if (!base) | 655 | if (!base) |
643 | return (instance_list != NULL); | 656 | return (G.instance_list != NULL); |
644 | 657 | ||
645 | for (inst = instance_list; inst; inst = inst->next) { | 658 | for (inst = G.instance_list; inst; inst = inst->next) { |
646 | if (!inst->base_device || !strcmp(base, inst->base_device)) { | 659 | if (!inst->base_device || !strcmp(base, inst->base_device)) { |
647 | free(base); | 660 | free(base); |
648 | return 1; | 661 | return 1; |
@@ -687,17 +700,17 @@ static int fs_match(struct fs_info *fs) | |||
687 | int n, ret, checked_type; | 700 | int n, ret, checked_type; |
688 | char *cp; | 701 | char *cp; |
689 | 702 | ||
690 | if (!fs_type_list) | 703 | if (!G.fs_type_list) |
691 | return 1; | 704 | return 1; |
692 | 705 | ||
693 | ret = 0; | 706 | ret = 0; |
694 | checked_type = 0; | 707 | checked_type = 0; |
695 | n = 0; | 708 | n = 0; |
696 | while (1) { | 709 | while (1) { |
697 | cp = fs_type_list[n]; | 710 | cp = G.fs_type_list[n]; |
698 | if (!cp) | 711 | if (!cp) |
699 | break; | 712 | break; |
700 | switch (fs_type_flag[n]) { | 713 | switch (G.fs_type_flag[n]) { |
701 | case FS_TYPE_FLAG_NORMAL: | 714 | case FS_TYPE_FLAG_NORMAL: |
702 | checked_type++; | 715 | checked_type++; |
703 | if (strcmp(cp, fs->type) == 0) | 716 | if (strcmp(cp, fs->type) == 0) |
@@ -717,7 +730,7 @@ static int fs_match(struct fs_info *fs) | |||
717 | if (checked_type == 0) | 730 | if (checked_type == 0) |
718 | return 1; | 731 | return 1; |
719 | 732 | ||
720 | return (fs_type_negated ? !ret : ret); | 733 | return (G.fs_type_negated ? !ret : ret); |
721 | } | 734 | } |
722 | 735 | ||
723 | /* Check if we should ignore this filesystem. */ | 736 | /* Check if we should ignore this filesystem. */ |
@@ -753,7 +766,7 @@ static int check_all(void) | |||
753 | smallint pass_done; | 766 | smallint pass_done; |
754 | int passno; | 767 | int passno; |
755 | 768 | ||
756 | if (verbose) | 769 | if (G.verbose) |
757 | puts("Checking all filesystems"); | 770 | puts("Checking all filesystems"); |
758 | 771 | ||
759 | /* | 772 | /* |
@@ -761,17 +774,17 @@ static int check_all(void) | |||
761 | * which should be ignored as done, and resolve any "auto" | 774 | * which should be ignored as done, and resolve any "auto" |
762 | * filesystem types (done as a side-effect of calling ignore()). | 775 | * filesystem types (done as a side-effect of calling ignore()). |
763 | */ | 776 | */ |
764 | for (fs = filesys_info; fs; fs = fs->next) | 777 | for (fs = G.filesys_info; fs; fs = fs->next) |
765 | if (ignore(fs)) | 778 | if (ignore(fs)) |
766 | fs->flags |= FLAG_DONE; | 779 | fs->flags |= FLAG_DONE; |
767 | 780 | ||
768 | /* | 781 | /* |
769 | * Find and check the root filesystem. | 782 | * Find and check the root filesystem. |
770 | */ | 783 | */ |
771 | if (!parallel_root) { | 784 | if (!G.parallel_root) { |
772 | for (fs = filesys_info; fs; fs = fs->next) { | 785 | for (fs = G.filesys_info; fs; fs = fs->next) { |
773 | if (LONE_CHAR(fs->mountpt, '/')) { | 786 | if (LONE_CHAR(fs->mountpt, '/')) { |
774 | if (!skip_root && !ignore(fs)) { | 787 | if (!G.skip_root && !ignore(fs)) { |
775 | fsck_device(fs /*, 1*/); | 788 | fsck_device(fs /*, 1*/); |
776 | status |= wait_many(FLAG_WAIT_ALL); | 789 | status |= wait_many(FLAG_WAIT_ALL); |
777 | if (status > EXIT_NONDESTRUCT) | 790 | if (status > EXIT_NONDESTRUCT) |
@@ -787,8 +800,8 @@ static int check_all(void) | |||
787 | * filesystem listed twice. | 800 | * filesystem listed twice. |
788 | * "Skip root" will skip _all_ root entries. | 801 | * "Skip root" will skip _all_ root entries. |
789 | */ | 802 | */ |
790 | if (skip_root) | 803 | if (G.skip_root) |
791 | for (fs = filesys_info; fs; fs = fs->next) | 804 | for (fs = G.filesys_info; fs; fs = fs->next) |
792 | if (LONE_CHAR(fs->mountpt, '/')) | 805 | if (LONE_CHAR(fs->mountpt, '/')) |
793 | fs->flags |= FLAG_DONE; | 806 | fs->flags |= FLAG_DONE; |
794 | 807 | ||
@@ -798,7 +811,7 @@ static int check_all(void) | |||
798 | not_done_yet = 0; | 811 | not_done_yet = 0; |
799 | pass_done = 1; | 812 | pass_done = 1; |
800 | 813 | ||
801 | for (fs = filesys_info; fs; fs = fs->next) { | 814 | for (fs = G.filesys_info; fs; fs = fs->next) { |
802 | if (bb_got_signal) | 815 | if (bb_got_signal) |
803 | break; | 816 | break; |
804 | if (fs->flags & FLAG_DONE) | 817 | if (fs->flags & FLAG_DONE) |
@@ -824,7 +837,7 @@ static int check_all(void) | |||
824 | /* | 837 | /* |
825 | * Spawn off the fsck process | 838 | * Spawn off the fsck process |
826 | */ | 839 | */ |
827 | fsck_device(fs /*, serialize*/); | 840 | fsck_device(fs /*, G.serialize*/); |
828 | fs->flags |= FLAG_DONE; | 841 | fs->flags |= FLAG_DONE; |
829 | 842 | ||
830 | /* | 843 | /* |
@@ -832,8 +845,8 @@ static int check_all(void) | |||
832 | * have a limit on the number of fsck's extant | 845 | * have a limit on the number of fsck's extant |
833 | * at one time, apply that limit. | 846 | * at one time, apply that limit. |
834 | */ | 847 | */ |
835 | if (serialize | 848 | if (G.serialize |
836 | || (max_running && (num_running >= max_running)) | 849 | || (G.num_running >= G.max_running) |
837 | ) { | 850 | ) { |
838 | pass_done = 0; | 851 | pass_done = 0; |
839 | break; | 852 | break; |
@@ -841,12 +854,12 @@ static int check_all(void) | |||
841 | } | 854 | } |
842 | if (bb_got_signal) | 855 | if (bb_got_signal) |
843 | break; | 856 | break; |
844 | if (verbose > 1) | 857 | if (G.verbose > 1) |
845 | printf("--waiting-- (pass %d)\n", passno); | 858 | printf("--waiting-- (pass %d)\n", passno); |
846 | status |= wait_many(pass_done ? FLAG_WAIT_ALL : | 859 | status |= wait_many(pass_done ? FLAG_WAIT_ALL : |
847 | FLAG_WAIT_ATLEAST_ONE); | 860 | FLAG_WAIT_ATLEAST_ONE); |
848 | if (pass_done) { | 861 | if (pass_done) { |
849 | if (verbose > 1) | 862 | if (G.verbose > 1) |
850 | puts("----------------------------------"); | 863 | puts("----------------------------------"); |
851 | passno++; | 864 | passno++; |
852 | } else | 865 | } else |
@@ -874,9 +887,9 @@ static void compile_fs_type(char *fs_type) | |||
874 | s++; | 887 | s++; |
875 | } | 888 | } |
876 | 889 | ||
877 | fs_type_list = xzalloc(num * sizeof(fs_type_list[0])); | 890 | G.fs_type_list = xzalloc(num * sizeof(G.fs_type_list[0])); |
878 | fs_type_flag = xzalloc(num * sizeof(fs_type_flag[0])); | 891 | G.fs_type_flag = xzalloc(num * sizeof(G.fs_type_flag[0])); |
879 | fs_type_negated = -1; /* not yet known is it negated or not */ | 892 | G.fs_type_negated = -1; /* not yet known is it negated or not */ |
880 | 893 | ||
881 | num = 0; | 894 | num = 0; |
882 | s = fs_type; | 895 | s = fs_type; |
@@ -898,18 +911,18 @@ static void compile_fs_type(char *fs_type) | |||
898 | if (is_prefixed_with(s, "opts=")) { | 911 | if (is_prefixed_with(s, "opts=")) { |
899 | s += 5; | 912 | s += 5; |
900 | loop_special_case: | 913 | loop_special_case: |
901 | fs_type_flag[num] = negate ? FS_TYPE_FLAG_NEGOPT : FS_TYPE_FLAG_OPT; | 914 | G.fs_type_flag[num] = negate ? FS_TYPE_FLAG_NEGOPT : FS_TYPE_FLAG_OPT; |
902 | } else { | 915 | } else { |
903 | if (fs_type_negated == -1) | 916 | if (G.fs_type_negated == -1) |
904 | fs_type_negated = negate; | 917 | G.fs_type_negated = negate; |
905 | if (fs_type_negated != negate) | 918 | if (G.fs_type_negated != negate) |
906 | bb_error_msg_and_die( | 919 | bb_error_msg_and_die( |
907 | "either all or none of the filesystem types passed to -t must be prefixed " | 920 | "either all or none of the filesystem types passed to -t must be prefixed " |
908 | "with 'no' or '!'"); | 921 | "with 'no' or '!'"); |
909 | } | 922 | } |
910 | comma = strchr(s, ','); | 923 | comma = strchrnul(s, ','); |
911 | fs_type_list[num++] = comma ? xstrndup(s, comma-s) : xstrdup(s); | 924 | G.fs_type_list[num++] = xstrndup(s, comma-s); |
912 | if (!comma) | 925 | if (*comma == '\0') |
913 | break; | 926 | break; |
914 | s = comma + 1; | 927 | s = comma + 1; |
915 | } | 928 | } |
@@ -917,8 +930,8 @@ static void compile_fs_type(char *fs_type) | |||
917 | 930 | ||
918 | static char **new_args(void) | 931 | static char **new_args(void) |
919 | { | 932 | { |
920 | args = xrealloc_vector(args, 2, num_args); | 933 | G.args = xrealloc_vector(G.args, 2, G.num_args); |
921 | return &args[num_args++]; | 934 | return &G.args[G.num_args++]; |
922 | } | 935 | } |
923 | 936 | ||
924 | int fsck_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 937 | int fsck_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
@@ -935,6 +948,8 @@ int fsck_main(int argc UNUSED_PARAM, char **argv) | |||
935 | smallint doall; | 948 | smallint doall; |
936 | smallint notitle; | 949 | smallint notitle; |
937 | 950 | ||
951 | INIT_G(); | ||
952 | |||
938 | /* we want wait() to be interruptible */ | 953 | /* we want wait() to be interruptible */ |
939 | signal_no_SA_RESTART_empty_mask(SIGINT, record_signo); | 954 | signal_no_SA_RESTART_empty_mask(SIGINT, record_signo); |
940 | signal_no_SA_RESTART_empty_mask(SIGTERM, record_signo); | 955 | signal_no_SA_RESTART_empty_mask(SIGTERM, record_signo); |
@@ -944,8 +959,8 @@ int fsck_main(int argc UNUSED_PARAM, char **argv) | |||
944 | opts_for_fsck = doall = notitle = 0; | 959 | opts_for_fsck = doall = notitle = 0; |
945 | devices = NULL; | 960 | devices = NULL; |
946 | num_devices = 0; | 961 | num_devices = 0; |
947 | new_args(); /* args[0] = NULL, will be replaced by fsck.<type> */ | 962 | new_args(); /* G.args[0] = NULL, will be replaced by fsck.<type> */ |
948 | /* instance_list = NULL; - in bss, so already zeroed */ | 963 | /* G.instance_list = NULL; - in bss, so already zeroed */ |
949 | 964 | ||
950 | while (*++argv) { | 965 | while (*++argv) { |
951 | int j; | 966 | int j; |
@@ -994,13 +1009,13 @@ int fsck_main(int argc UNUSED_PARAM, char **argv) | |||
994 | goto next_arg; | 1009 | goto next_arg; |
995 | #endif | 1010 | #endif |
996 | case 'V': | 1011 | case 'V': |
997 | verbose++; | 1012 | G.verbose++; |
998 | break; | 1013 | break; |
999 | case 'N': | 1014 | case 'N': |
1000 | noexecute = 1; | 1015 | G.noexecute = 1; |
1001 | break; | 1016 | break; |
1002 | case 'R': | 1017 | case 'R': |
1003 | skip_root = 1; | 1018 | G.skip_root = 1; |
1004 | break; | 1019 | break; |
1005 | case 'T': | 1020 | case 'T': |
1006 | notitle = 1; | 1021 | notitle = 1; |
@@ -1009,13 +1024,13 @@ int fsck_main(int argc UNUSED_PARAM, char **argv) | |||
1009 | like_mount = 1; | 1024 | like_mount = 1; |
1010 | break; */ | 1025 | break; */ |
1011 | case 'P': | 1026 | case 'P': |
1012 | parallel_root = 1; | 1027 | G.parallel_root = 1; |
1013 | break; | 1028 | break; |
1014 | case 's': | 1029 | case 's': |
1015 | serialize = 1; | 1030 | G.serialize = 1; |
1016 | break; | 1031 | break; |
1017 | case 't': | 1032 | case 't': |
1018 | if (fstype) | 1033 | if (G.fstype) |
1019 | bb_show_usage(); | 1034 | bb_show_usage(); |
1020 | if (arg[++j]) | 1035 | if (arg[++j]) |
1021 | tmp = &arg[j]; | 1036 | tmp = &arg[j]; |
@@ -1023,8 +1038,8 @@ int fsck_main(int argc UNUSED_PARAM, char **argv) | |||
1023 | tmp = *argv; | 1038 | tmp = *argv; |
1024 | else | 1039 | else |
1025 | bb_show_usage(); | 1040 | bb_show_usage(); |
1026 | fstype = xstrdup(tmp); | 1041 | G.fstype = xstrdup(tmp); |
1027 | compile_fs_type(fstype); | 1042 | compile_fs_type(G.fstype); |
1028 | goto next_arg; | 1043 | goto next_arg; |
1029 | case '?': | 1044 | case '?': |
1030 | bb_show_usage(); | 1045 | bb_show_usage(); |
@@ -1045,12 +1060,13 @@ int fsck_main(int argc UNUSED_PARAM, char **argv) | |||
1045 | } | 1060 | } |
1046 | } | 1061 | } |
1047 | if (getenv("FSCK_FORCE_ALL_PARALLEL")) | 1062 | if (getenv("FSCK_FORCE_ALL_PARALLEL")) |
1048 | force_all_parallel = 1; | 1063 | G.force_all_parallel = 1; |
1049 | tmp = getenv("FSCK_MAX_INST"); | 1064 | tmp = getenv("FSCK_MAX_INST"); |
1065 | G.max_running = INT_MAX; | ||
1050 | if (tmp) | 1066 | if (tmp) |
1051 | max_running = xatoi(tmp); | 1067 | G.max_running = xatoi(tmp); |
1052 | new_args(); /* args[num_args - 2] will be replaced by <device> */ | 1068 | new_args(); /* G.args[G.num_args - 2] will be replaced by <device> */ |
1053 | new_args(); /* args[num_args - 1] is the last, NULL element */ | 1069 | new_args(); /* G.args[G.num_args - 1] is the last, NULL element */ |
1054 | 1070 | ||
1055 | if (!notitle) | 1071 | if (!notitle) |
1056 | puts("fsck (busybox "BB_VER", "BB_BT")"); | 1072 | puts("fsck (busybox "BB_VER", "BB_BT")"); |
@@ -1062,10 +1078,10 @@ int fsck_main(int argc UNUSED_PARAM, char **argv) | |||
1062 | fstab = "/etc/fstab"; | 1078 | fstab = "/etc/fstab"; |
1063 | load_fs_info(fstab); | 1079 | load_fs_info(fstab); |
1064 | 1080 | ||
1065 | /*interactive = (num_devices == 1) | serialize;*/ | 1081 | /*interactive = (num_devices == 1) | G.serialize;*/ |
1066 | 1082 | ||
1067 | if (num_devices == 0) | 1083 | if (num_devices == 0) |
1068 | /*interactive =*/ serialize = doall = 1; | 1084 | /*interactive =*/ G.serialize = doall = 1; |
1069 | if (doall) | 1085 | if (doall) |
1070 | return check_all(); | 1086 | return check_all(); |
1071 | 1087 | ||
@@ -1081,13 +1097,13 @@ int fsck_main(int argc UNUSED_PARAM, char **argv) | |||
1081 | fs = create_fs_device(devices[i], "", "auto", NULL, -1); | 1097 | fs = create_fs_device(devices[i], "", "auto", NULL, -1); |
1082 | fsck_device(fs /*, interactive */); | 1098 | fsck_device(fs /*, interactive */); |
1083 | 1099 | ||
1084 | if (serialize | 1100 | if (G.serialize |
1085 | || (max_running && (num_running >= max_running)) | 1101 | || (G.num_running >= G.max_running) |
1086 | ) { | 1102 | ) { |
1087 | int exit_status = wait_one(0); | 1103 | int exit_status = wait_one(0); |
1088 | if (exit_status >= 0) | 1104 | if (exit_status >= 0) |
1089 | status |= exit_status; | 1105 | status |= exit_status; |
1090 | if (verbose > 1) | 1106 | if (G.verbose > 1) |
1091 | puts("----------------------------------"); | 1107 | puts("----------------------------------"); |
1092 | } | 1108 | } |
1093 | } | 1109 | } |