aboutsummaryrefslogtreecommitdiff
path: root/e2fsprogs/fsck.c
diff options
context:
space:
mode:
Diffstat (limited to 'e2fsprogs/fsck.c')
-rw-r--r--e2fsprogs/fsck.c272
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
128static char **args; 140struct globals {
129static int num_args; 141 char **args;
130static 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
135static char **fs_type_list; 148 char **fs_type_list;
136static uint8_t *fs_type_flag; 149 uint8_t *fs_type_flag;
137static smallint fs_type_negated; 150 smallint fs_type_negated;
138 151
139static smallint noexecute; 152 smallint noexecute;
140static smallint serialize; 153 smallint serialize;
141static smallint skip_root; 154 smallint skip_root;
142/* static smallint like_mount; */ 155 /* smallint like_mount; */
143static smallint parallel_root; 156 smallint parallel_root;
144static 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
147static smallint progress; 161 smallint progress;
148static int progress_fd; 162 int progress_fd;
149#endif 163#endif
150 164
151static int num_running; 165 int num_running;
152static int max_running; 166 int max_running;
153static char *fstype; 167 char *fstype;
154static struct fs_info *filesys_info; 168 struct fs_info *filesys_info;
155static struct fs_info *filesys_last; 169 struct fs_info *filesys_last;
156static 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 */
372static void kill_all_if_got_signal(void) 392static 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
918static char **new_args(void) 931static 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
924int fsck_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 937int 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 }