Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/e2fsprogs/fsck.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 532 by niro, Sat Sep 1 22:45:15 2007 UTC revision 816 by niro, Fri Apr 24 18:33:46 2009 UTC
# Line 37  Line 37 
37   * It doesn't guess filesystem types from on-disk format.   * It doesn't guess filesystem types from on-disk format.
38   */   */
39    
40  #include "busybox.h"  #include "libbb.h"
41    
42    /* "progress indicator" code is somewhat buggy and ext[23] specific.
43     * We should be filesystem agnostic. IOW: there should be a well-defined
44     * API for fsck.something, NOT ad-hoc hacks in generic fsck. */
45    #define DO_PROGRESS_INDICATOR 0
46    
47  #define EXIT_OK          0  #define EXIT_OK          0
48  #define EXIT_NONDESTRUCT 1  #define EXIT_NONDESTRUCT 1
# Line 57  struct fs_info { Line 62  struct fs_info {
62   char *mountpt;   char *mountpt;
63   char *type;   char *type;
64   char *opts;   char *opts;
  int freq;  
65   int passno;   int passno;
66   int flags;   int flags;
67  };  };
# Line 71  struct fsck_instance { Line 75  struct fsck_instance {
75   struct fsck_instance *next;   struct fsck_instance *next;
76   int pid;   int pid;
77   int flags;   int flags;
78   int exit_status;  #if DO_PROGRESS_INDICATOR
79   time_t start_time;   time_t start_time;
80    #endif
81   char *prog;   char *prog;
  char *type;  
82   char *device;   char *device;
83   char *base_device; /* /dev/hda for /dev/hdaN etc */   char *base_device; /* /dev/hda for /dev/hdaN etc */
84  };  };
85    
86  static const char *const ignored_types[] = {  static const char ignored_types[] ALIGN1 =
87   "ignore",   "ignore\0"
88   "iso9660",   "iso9660\0"
89   "nfs",   "nfs\0"
90   "proc",   "proc\0"
91   "sw",   "sw\0"
92   "swap",   "swap\0"
93   "tmpfs",   "tmpfs\0"
94   "devpts",   "devpts\0";
  NULL  
 };  
95    
96  #if 0  #if 0
97  static const char *const really_wanted[] = {  static const char really_wanted[] ALIGN1 =
98   "minix",   "minix\0"
99   "ext2",   "ext2\0"
100   "ext3",   "ext3\0"
101   "jfs",   "jfs\0"
102   "reiserfs",   "reiserfs\0"
103   "xiafs",   "xiafs\0"
104   "xfs",   "xfs\0";
  NULL  
 };  
105  #endif  #endif
106    
107  #define BASE_MD "/dev/md"  #define BASE_MD "/dev/md"
# Line 129  static smallint notitle; Line 129  static smallint notitle;
129  static smallint parallel_root;  static smallint parallel_root;
130  static smallint force_all_parallel;  static smallint force_all_parallel;
131    
 /* "progress indicator" code is somewhat buggy and ext[23] specific.  
  * We should be filesystem agnostic. IOW: there should be a well-defined  
  * API for fsck.something, NOT ad-hoc hacks in generic fsck. */  
 #define DO_PROGRESS_INDICATOR 0  
132  #if DO_PROGRESS_INDICATOR  #if DO_PROGRESS_INDICATOR
133  static smallint progress;  static smallint progress;
134  static int progress_fd;  static int progress_fd;
# Line 277  static void free_instance(struct fsck_in Line 273  static void free_instance(struct fsck_in
273    
274  static struct fs_info *create_fs_device(const char *device, const char *mntpnt,  static struct fs_info *create_fs_device(const char *device, const char *mntpnt,
275   const char *type, const char *opts,   const char *type, const char *opts,
276   int freq, int passno)   int passno)
277  {  {
278   struct fs_info *fs;   struct fs_info *fs;
279    
280   fs = xzalloc(sizeof(*fs));   fs = xzalloc(sizeof(*fs));
281   fs->device = xstrdup(device);   fs->device = xstrdup(device);
282   fs->mountpt = xstrdup(mntpnt);   fs->mountpt = xstrdup(mntpnt);
283     if (strchr(type, ','))
284     type = (char *)"auto";
285   fs->type = xstrdup(type);   fs->type = xstrdup(type);
286   fs->opts = xstrdup(opts ? opts : "");   fs->opts = xstrdup(opts ? opts : "");
287   fs->freq = freq;   fs->passno = passno < 0 ? 1 : passno;
  fs->passno = passno;  
288   /*fs->flags = 0; */   /*fs->flags = 0; */
289   /*fs->next = NULL; */   /*fs->next = NULL; */
290    
# Line 300  static struct fs_info *create_fs_device( Line 297  static struct fs_info *create_fs_device(
297   return fs;   return fs;
298  }  }
299    
 static void strip_line(char *line)  
 {  
  char *p = line + strlen(line) - 1;  
   
  while (*line) {  
  if (*p != '\n' && *p != '\r')  
  break;  
  *p-- = '\0';  
  }  
 }  
   
 static char *parse_word(char **buf)  
 {  
  char *word, *next;  
   
  word = *buf;  
  if (*word == '\0')  
  return NULL;  
   
  word = skip_whitespace(word);  
  next = skip_non_whitespace(word);  
  if (*next)  
  *next++ = '\0';  
  *buf = next;  
  return word;  
 }  
   
 static void parse_escape(char *word)  
 {  
  char *q, c;  
  const char *p;  
   
  if (!word)  
  return;  
   
  for (p = q = word; *p; q++) {  
  c = *p++;  
  if (c != '\\') {  
  *q = c;  
  } else {  
  *q = bb_process_escape_sequence(&p);  
  }  
  }  
  *q = '\0';  
 }  
   
 static int parse_fstab_line(char *line, struct fs_info **ret_fs)  
 {  
  char *device, *mntpnt, *type, *opts, *freq, *passno, *cp;  
  struct fs_info *fs;  
   
  *ret_fs = 0;  
  strip_line(line);  
  cp = strchr(line, '#');  
  if (cp)  
  *cp = '\0'; /* Ignore everything after the comment char */  
  cp = line;  
   
  device = parse_word(&cp);  
  if (!device) return 0; /* Allow blank lines */  
  mntpnt = parse_word(&cp);  
  type = parse_word(&cp);  
  opts = parse_word(&cp);  
  freq = parse_word(&cp);  
  passno = parse_word(&cp);  
   
  if (!mntpnt || !type)  
  return -1;  
   
  parse_escape(device);  
  parse_escape(mntpnt);  
  parse_escape(type);  
  parse_escape(opts);  
  parse_escape(freq);  
  parse_escape(passno);  
   
  if (strchr(type, ','))  
  type = NULL;  
   
  fs = create_fs_device(device, mntpnt, type ? type : "auto", opts,  
     freq ? atoi(freq) : -1,  
     passno ? atoi(passno) : -1);  
  *ret_fs = fs;  
  return 0;  
 }  
   
300  /* Load the filesystem database from /etc/fstab */  /* Load the filesystem database from /etc/fstab */
301  static void load_fs_info(const char *filename)  static void load_fs_info(const char *filename)
302  {  {
303   FILE *f;   FILE *fstab;
304   int lineno = 0;   struct mntent mte;
  int old_fstab = 1;  
305   struct fs_info *fs;   struct fs_info *fs;
306    
307   f = fopen_or_warn(filename, "r");   fstab = setmntent(filename, "r");
308   if (f == NULL) {   if (!fstab) {
309   /*bb_perror_msg("WARNING: cannot open %s", filename);*/   bb_perror_msg("cannot read %s", filename);
310   return;   return;
311   }   }
312   while (1) {  
313   int r;   // Loop through entries
314   char *buf = xmalloc_getline(f);   while (getmntent_r(fstab, &mte, bb_common_bufsiz1, COMMON_BUFSIZE)) {
315   if (!buf) break;   //bb_info_msg("CREATE[%s][%s][%s][%s][%d]", mte.mnt_fsname, mte.mnt_dir,
316   r = parse_fstab_line(buf, &fs);   // mte.mnt_type, mte.mnt_opts,
317   free(buf);   // mte.mnt_passno);
318   lineno++;   fs = create_fs_device(mte.mnt_fsname, mte.mnt_dir,
319   if (r < 0) {   mte.mnt_type, mte.mnt_opts,
320   bb_error_msg("WARNING: bad format "   mte.mnt_passno);
  "on line %d of %s", lineno, filename);  
  continue;  
  }  
  if (!fs)  
  continue;  
  if (fs->passno < 0)  
  fs->passno = 0;  
  else  
  old_fstab = 0;  
  }  
  fclose(f);  
   
  if (old_fstab) {  
  fputs("\007"  
 "WARNING: Your /etc/fstab does not contain the fsck passno field.\n"  
 "I will kludge around things for you, but you should fix\n"  
 "your /etc/fstab file as soon as you can.\n\n", stderr);  
  for (fs = filesys_info; fs; fs = fs->next) {  
  fs->passno = 1;  
  }  
321   }   }
322     endmntent(fstab);
323  }  }
324    
325  /* Lookup filesys in /etc/fstab and return the corresponding entry. */  /* Lookup filesys in /etc/fstab and return the corresponding entry. */
# Line 484  static void kill_all_if_cancel_requested Line 375  static void kill_all_if_cancel_requested
375    
376  /*  /*
377   * Wait for one child process to exit; when it does, unlink it from   * Wait for one child process to exit; when it does, unlink it from
378   * the list of executing child processes, and return it.   * the list of executing child processes, free, and return its exit status.
379     * If there is no exited child, return -1.
380   */   */
381  static struct fsck_instance *wait_one(int flags)  static int wait_one(int flags)
382  {  {
383   int status;   int status;
384   int sig;   int sig;
# Line 494  static struct fsck_instance *wait_one(in Line 386  static struct fsck_instance *wait_one(in
386   pid_t pid;   pid_t pid;
387    
388   if (!instance_list)   if (!instance_list)
389   return NULL;   return -1;
390     /* if (noexecute) { already returned -1; } */
  if (noexecute) {  
  inst = instance_list;  
  prev = NULL;  
 #ifdef RANDOM_DEBUG  
  while (inst->next && (random() & 1)) {  
  prev = inst;  
  inst = inst->next;  
  }  
 #endif  
  inst->exit_status = 0;  
  goto ret_inst;  
  }  
   
  /*  
  * gcc -Wall fails saving throw against stupidity  
  * (inst and prev are thought to be uninitialized variables)  
  */  
  inst = prev = NULL;  
391    
392   do {   while (1) {
393   pid = waitpid(-1, &status, flags);   pid = waitpid(-1, &status, flags);
394   kill_all_if_cancel_requested();   kill_all_if_cancel_requested();
395   if (pid == 0 && (flags & WNOHANG))   if (pid == 0) /* flags == WNOHANG and no children exited */
396   return NULL;   return -1;
397   if (pid < 0) {   if (pid < 0) {
398   if (errno == EINTR || errno == EAGAIN)   if (errno == EINTR)
399   continue;   continue;
400   if (errno == ECHILD) {   if (errno == ECHILD) { /* paranoia */
401   bb_error_msg("wait: no more child process?!?");   bb_error_msg("wait: no more children");
402   return NULL;   return -1;
403   }   }
404   bb_perror_msg("wait");   bb_perror_msg("wait");
405   continue;   continue;
406   }   }
407   prev = NULL;   prev = NULL;
408   inst = instance_list;   inst = instance_list;
409   while (inst) {   do {
410   if (inst->pid == pid)   if (inst->pid == pid)
411   break;   goto child_died;
412   prev = inst;   prev = inst;
413   inst = inst->next;   inst = inst->next;
414   }   } while (inst);
415   } while (!inst);   }
416     child_died:
417    
418   if (WIFEXITED(status))   if (WIFEXITED(status))
419   status = WEXITSTATUS(status);   status = WEXITSTATUS(status);
# Line 546  static struct fsck_instance *wait_one(in Line 421  static struct fsck_instance *wait_one(in
421   sig = WTERMSIG(status);   sig = WTERMSIG(status);
422   status = EXIT_UNCORRECTED;   status = EXIT_UNCORRECTED;
423   if (sig != SIGINT) {   if (sig != SIGINT) {
424   printf("Warning... %s %s exited "   printf("Warning: %s %s terminated "
425   "with signal %d\n",   "by signal %d\n",
426   inst->prog, inst->device, sig);   inst->prog, inst->device, sig);
427   status = EXIT_ERROR;   status = EXIT_ERROR;
428   }   }
# Line 556  static struct fsck_instance *wait_one(in Line 431  static struct fsck_instance *wait_one(in
431   inst->prog, inst->device, status);   inst->prog, inst->device, status);
432   status = EXIT_ERROR;   status = EXIT_ERROR;
433   }   }
  inst->exit_status = status;  
434    
435  #if DO_PROGRESS_INDICATOR  #if DO_PROGRESS_INDICATOR
436   if (progress && (inst->flags & FLAG_PROGRESS) && !progress_active()) {   if (progress && (inst->flags & FLAG_PROGRESS) && !progress_active()) {
# Line 585  static struct fsck_instance *wait_one(in Line 459  static struct fsck_instance *wait_one(in
459   }   }
460  #endif  #endif
461    
  ret_inst:  
462   if (prev)   if (prev)
463   prev->next = inst->next;   prev->next = inst->next;
464   else   else
465   instance_list = inst->next;   instance_list = inst->next;
466   if (verbose > 1)   if (verbose > 1)
467   printf("Finished with %s (exit status %d)\n",   printf("Finished with %s (exit status %d)\n",
468         inst->device, inst->exit_status);         inst->device, status);
469   num_running--;   num_running--;
470   return inst;   free_instance(inst);
471    
472     return status;
473  }  }
474    
 #define FLAG_WAIT_ALL           0  
 #define FLAG_WAIT_ATLEAST_ONE   1  
475  /*  /*
476   * Wait until all executing child processes have exited; return the   * Wait until all executing child processes have exited; return the
477   * logical OR of all of their exit code values.   * logical OR of all of their exit code values.
478   */   */
479    #define FLAG_WAIT_ALL           0
480    #define FLAG_WAIT_ATLEAST_ONE   WNOHANG
481  static int wait_many(int flags)  static int wait_many(int flags)
482  {  {
483   struct fsck_instance *inst;   int exit_status;
484   int global_status = 0;   int global_status = 0;
485   int wait_flags = 0;   int wait_flags = 0;
486    
487   while ((inst = wait_one(wait_flags))) {   while ((exit_status = wait_one(wait_flags)) != -1) {
488   global_status |= inst->exit_status;   global_status |= exit_status;
489   free_instance(inst);   wait_flags |= flags;
 #ifdef RANDOM_DEBUG  
  if (noexecute && (flags & WNOHANG) && !(random() % 3))  
  break;  
 #endif  
  if (flags & FLAG_WAIT_ATLEAST_ONE)  
  wait_flags = WNOHANG;  
490   }   }
491   return global_status;   return global_status;
492  }  }
# Line 626  static int wait_many(int flags) Line 495  static int wait_many(int flags)
495   * Execute a particular fsck program, and link it into the list of   * Execute a particular fsck program, and link it into the list of
496   * child processes we are waiting for.   * child processes we are waiting for.
497   */   */
498  static void execute(const char *type, const char *device, const char *mntpt,  static void execute(const char *type, const char *device,
499   int interactive)   const char *mntpt /*, int interactive */)
500  {  {
501   char *argv[num_args + 4]; /* see count below: */   char *argv[num_args + 4]; /* see count below: */
502   int argc;   int argc;
# Line 635  static void execute(const char *type, co Line 504  static void execute(const char *type, co
504   struct fsck_instance *inst;   struct fsck_instance *inst;
505   pid_t pid;   pid_t pid;
506    
  inst = xzalloc(sizeof(*inst));  
   
507   argv[0] = xasprintf("fsck.%s", type); /* 1 */   argv[0] = xasprintf("fsck.%s", type); /* 1 */
508   for (i = 0; i < num_args; i++)   for (i = 0; i < num_args; i++)
509   argv[i+1] = args[i]; /* num_args */   argv[i+1] = args[i]; /* num_args */
# Line 653  static void execute(const char *type, co Line 520  static void execute(const char *type, co
520   }   }
521  #endif  #endif
522    
523   argv[argc++] = xstrdup(device); /* 1 */   argv[argc++] = (char*)device; /* 1 */
524   argv[argc] = NULL; /* 1 */   argv[argc] = NULL; /* 1 */
525    
526   if (verbose || noexecute) {   if (verbose || noexecute) {
# Line 661  static void execute(const char *type, co Line 528  static void execute(const char *type, co
528   mntpt ? mntpt : device);   mntpt ? mntpt : device);
529   for (i = 0; i < argc; i++)   for (i = 0; i < argc; i++)
530   printf(" %s", argv[i]);   printf(" %s", argv[i]);
531   puts("");   bb_putchar('\n');
532   }   }
533    
534   /* Fork and execute the correct program. */   /* Fork and execute the correct program. */
535   pid = -1;   pid = -1;
536   if (!noexecute) {   if (!noexecute) {
537   pid = fork(); /* TODO: NOMMU friendly way (vfork)? */   pid = spawn(argv);
538   if (pid < 0)   if (pid < 0)
539   bb_perror_msg_and_die("fork");   bb_simple_perror_msg(argv[0]);
  if (pid == 0) {  
  /* Child */  
  if (!interactive) {  
  /* NB: e2fsck will complain because of this!  
  * Use "fsck -s" to avoid... */  
  close(0);  
  }  
  execvp(argv[0], argv);  
  bb_perror_msg_and_die("%s", argv[0]);  
  }  
540   }   }
541    
542   for (i = num_args+1; i < argc; i++)  #if DO_PROGRESS_INDICATOR
543   free(argv[i]);   free(argv[num_args + 1]);
544    #endif
545    
546     /* No child, so don't record an instance */
547     if (pid <= 0) {
548     free(argv[0]);
549     return;
550     }
551    
552     inst = xzalloc(sizeof(*inst));
553   inst->pid = pid;   inst->pid = pid;
554   inst->prog = argv[0];   inst->prog = argv[0];
  inst->type = xstrdup(type);  
555   inst->device = xstrdup(device);   inst->device = xstrdup(device);
556   inst->base_device = base_device(device);   inst->base_device = base_device(device);
557    #if DO_PROGRESS_INDICATOR
558   inst->start_time = time(NULL);   inst->start_time = time(NULL);
559    #endif
560    
561   /* Add to the list of running fsck's.   /* Add to the list of running fsck's.
562   * (was adding to the end, but adding to the front is simpler...) */   * (was adding to the end, but adding to the front is simpler...) */
# Line 708  static void execute(const char *type, co Line 574  static void execute(const char *type, co
574   * If the type isn't specified by the user, then use either the type   * If the type isn't specified by the user, then use either the type
575   * specified in /etc/fstab, or "auto".   * specified in /etc/fstab, or "auto".
576   */   */
577  static void fsck_device(struct fs_info *fs, int interactive)  static void fsck_device(struct fs_info *fs /*, int interactive */)
578  {  {
579   const char *type;   const char *type;
580    
# Line 735  static void fsck_device(struct fs_info * Line 601  static void fsck_device(struct fs_info *
601   }   }
602    
603   num_running++;   num_running++;
604   execute(type, fs->device, fs->mountpt, interactive);   execute(type, fs->device, fs->mountpt /*, interactive */);
605  }  }
606    
607  /*  /*
# Line 863  static int ignore(struct fs_info *fs) Line 729  static int ignore(struct fs_info *fs)
729   return 1;   return 1;
730    
731   /* Are we ignoring this type? */   /* Are we ignoring this type? */
732   if (index_in_str_array(ignored_types, fs->type) >= 0)   if (index_in_strings(ignored_types, fs->type) >= 0)
733   return 1;   return 1;
734    
735   /* We can and want to check this file system type. */   /* We can and want to check this file system type. */
# Line 887  static int check_all(void) Line 753  static int check_all(void)
753   * which should be ignored as done, and resolve any "auto"   * which should be ignored as done, and resolve any "auto"
754   * filesystem types (done as a side-effect of calling ignore()).   * filesystem types (done as a side-effect of calling ignore()).
755   */   */
756   for (fs = filesys_info; fs; fs = fs->next) {   for (fs = filesys_info; fs; fs = fs->next)
757   if (ignore(fs))   if (ignore(fs))
758   fs->flags |= FLAG_DONE;   fs->flags |= FLAG_DONE;
  }  
759    
760   /*   /*
761   * Find and check the root filesystem.   * Find and check the root filesystem.
762   */   */
763   if (!parallel_root) {   if (!parallel_root) {
764   for (fs = filesys_info; fs; fs = fs->next) {   for (fs = filesys_info; fs; fs = fs->next) {
765   if (LONE_CHAR(fs->mountpt, '/'))   if (LONE_CHAR(fs->mountpt, '/')) {
766     if (!skip_root && !ignore(fs)) {
767     fsck_device(fs /*, 1*/);
768     status |= wait_many(FLAG_WAIT_ALL);
769     if (status > EXIT_NONDESTRUCT)
770     return status;
771     }
772     fs->flags |= FLAG_DONE;
773   break;   break;
  }  
  if (fs) {  
  if (!skip_root && !ignore(fs)) {  
  fsck_device(fs, 1);  
  status |= wait_many(FLAG_WAIT_ALL);  
  if (status > EXIT_NONDESTRUCT)  
  return status;  
774   }   }
  fs->flags |= FLAG_DONE;  
775   }   }
776   }   }
777   /*   /*
778   * This is for the bone-headed user who enters the root   * This is for the bone-headed user who has root
779   * filesystem twice.  Skip root will skip all root entries.   * filesystem listed twice.
780     * "Skip root" will skip _all_ root entries.
781   */   */
782   if (skip_root)   if (skip_root)
783   for (fs = filesys_info; fs; fs = fs->next)   for (fs = filesys_info; fs; fs = fs->next)
# Line 932  static int check_all(void) Line 797  static int check_all(void)
797   continue;   continue;
798   /*   /*
799   * If the filesystem's pass number is higher   * If the filesystem's pass number is higher
800   * than the current pass number, then we don't   * than the current pass number, then we didn't
801   * do it yet.   * do it yet.
802   */   */
803   if (fs->passno > passno) {   if (fs->passno > passno) {
# Line 951  static int check_all(void) Line 816  static int check_all(void)
816   /*   /*
817   * Spawn off the fsck process   * Spawn off the fsck process
818   */   */
819   fsck_device(fs, serialize);   fsck_device(fs /*, serialize*/);
820   fs->flags |= FLAG_DONE;   fs->flags |= FLAG_DONE;
821    
822   /*   /*
# Line 995  static void compile_fs_type(char *fs_typ Line 860  static void compile_fs_type(char *fs_typ
860   int num = 2;   int num = 2;
861   smallint negate;   smallint negate;
862    
863   if (fs_type) {   s = fs_type;
864   s = fs_type;   while ((s = strchr(s, ','))) {
865   while ((s = strchr(s, ','))) {   num++;
866   num++;   s++;
  s++;  
  }  
867   }   }
868    
869   fs_type_list = xzalloc(num * sizeof(fs_type_list[0]));   fs_type_list = xzalloc(num * sizeof(fs_type_list[0]));
870   fs_type_flag = xzalloc(num * sizeof(fs_type_flag[0]));   fs_type_flag = xzalloc(num * sizeof(fs_type_flag[0]));
871   fs_type_negated = -1; /* not yet known is it negated or not */   fs_type_negated = -1; /* not yet known is it negated or not */
872    
  if (!fs_type)  
  return;  
   
873   num = 0;   num = 0;
874   s = fs_type;   s = fs_type;
875   while (1) {   while (1) {
# Line 1047  static void compile_fs_type(char *fs_typ Line 907  static void compile_fs_type(char *fs_typ
907   }   }
908  }  }
909    
910  static void parse_args(int argc, char *argv[])  static void parse_args(char **argv)
911  {  {
912   int i, j;   int i, j;
913   char *arg, *tmp;   char *arg, *tmp;
914   char *options = NULL;   char *options;
915   int optpos = 0;   int optpos;
916   int opts_for_fsck = 0;   int opts_for_fsck = 0;
917    
918   /* in bss, so already zeroed   /* in bss, so already zeroed
# Line 1061  static void parse_args(int argc, char *a Line 921  static void parse_args(int argc, char *a
921   instance_list = NULL;   instance_list = NULL;
922   */   */
923    
924  /* TODO: getopt32 */   for (i = 1; argv[i]; i++) {
  for (i = 1; i < argc; i++) {  
925   arg = argv[i];   arg = argv[i];
926    
927   /* "/dev/blk" or "/path" or "UUID=xxx" or "LABEL=xxx" */   /* "/dev/blk" or "/path" or "UUID=xxx" or "LABEL=xxx" */
# Line 1070  static void parse_args(int argc, char *a Line 929  static void parse_args(int argc, char *a
929  // FIXME: must check that arg is a blkdev, or resolve  // FIXME: must check that arg is a blkdev, or resolve
930  // "/path", "UUID=xxx" or "LABEL=xxx" into block device name  // "/path", "UUID=xxx" or "LABEL=xxx" into block device name
931  // ("UUID=xxx"/"LABEL=xxx" can probably shifted to fsck.auto duties)  // ("UUID=xxx"/"LABEL=xxx" can probably shifted to fsck.auto duties)
932   devices = xrealloc(devices, (num_devices+1) * sizeof(devices[0]));   devices = xrealloc_vector(devices, 2, num_devices);
933   devices[num_devices++] = xstrdup(arg);   devices[num_devices++] = xstrdup(arg);
934   continue;   continue;
935   }   }
936    
937   if (arg[0] != '-' || opts_for_fsck) {   if (arg[0] != '-' || opts_for_fsck) {
938   args = xrealloc(args, (num_args+1) * sizeof(args[0]));   args = xrealloc_vector(args, 2, num_args);
939   args[num_args++] = xstrdup(arg);   args[num_args++] = xstrdup(arg);
940   continue;   continue;
941   }   }
942    
943     if (LONE_CHAR(arg + 1, '-')) { /* "--" ? */
944     opts_for_fsck = 1;
945     continue;
946     }
947    
948     optpos = 0;
949     options = NULL;
950   for (j = 1; arg[j]; j++) {   for (j = 1; arg[j]; j++) {
  if (opts_for_fsck) {  
  optpos++;  
  /* one extra for '\0' */  
  options = xrealloc(options, optpos + 2);  
  options[optpos] = arg[j];  
  continue;  
  }  
951   switch (arg[j]) {   switch (arg[j]) {
952   case 'A':   case 'A':
953   doall = 1;   doall = 1;
# Line 1101  static void parse_args(int argc, char *a Line 960  static void parse_args(int argc, char *a
960   goto next_arg;   goto next_arg;
961   }   }
962   /* -C n */   /* -C n */
963   progress_fd = xatoi_u(argv[++i]);   if (!argv[++i]) bb_show_usage();
964     progress_fd = xatoi_u(argv[i]);
965   goto next_arg;   goto next_arg;
966  #endif  #endif
967   case 'V':   case 'V':
# Line 1130  static void parse_args(int argc, char *a Line 990  static void parse_args(int argc, char *a
990   bb_show_usage();   bb_show_usage();
991   if (arg[++j])   if (arg[++j])
992   tmp = &arg[j];   tmp = &arg[j];
993   else if (++i < argc)   else if (argv[++i])
994   tmp = argv[i];   tmp = argv[i];
995   else   else
996   bb_show_usage();   bb_show_usage();
997   fstype = xstrdup(tmp);   fstype = xstrdup(tmp);
998   compile_fs_type(fstype);   compile_fs_type(fstype);
999   goto next_arg;   goto next_arg;
  case '-':  
  opts_for_fsck++;  
  break;  
1000   case '?':   case '?':
1001   bb_show_usage();   bb_show_usage();
1002   break;   break;
# Line 1155  static void parse_args(int argc, char *a Line 1012  static void parse_args(int argc, char *a
1012   if (optpos) {   if (optpos) {
1013   options[0] = '-';   options[0] = '-';
1014   options[optpos + 1] = '\0';   options[optpos + 1] = '\0';
1015   args = xrealloc(args, (num_args+1) * sizeof(args[0]));   args = xrealloc_vector(args, 2, num_args);
1016   args[num_args++] = options;   args[num_args++] = options;
  optpos = 0;  
  options = NULL;  
1017   }   }
1018   }   }
1019   if (getenv("FSCK_FORCE_ALL_PARALLEL"))   if (getenv("FSCK_FORCE_ALL_PARALLEL"))
# Line 1168  static void parse_args(int argc, char *a Line 1023  static void parse_args(int argc, char *a
1023   max_running = xatoi(tmp);   max_running = xatoi(tmp);
1024  }  }
1025    
1026  static void signal_cancel(int sig ATTRIBUTE_UNUSED)  static void signal_cancel(int sig UNUSED_PARAM)
1027  {  {
1028   cancel_requested = 1;   cancel_requested = 1;
1029  }  }
1030    
1031  int fsck_main(int argc, char *argv[])  int fsck_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1032    int fsck_main(int argc UNUSED_PARAM, char **argv)
1033  {  {
1034   int i, status = 0;   int i, status;
1035   int interactive;   /*int interactive;*/
1036   const char *fstab;   const char *fstab;
1037   struct fs_info *fs;   struct fs_info *fs;
  struct sigaction sa;  
1038    
1039   memset(&sa, 0, sizeof(sa));   /* we want wait() to be interruptible */
1040   sa.sa_handler = signal_cancel;   signal_no_SA_RESTART_empty_mask(SIGINT, signal_cancel);
1041   sigaction(SIGINT, &sa, 0);   signal_no_SA_RESTART_empty_mask(SIGTERM, signal_cancel);
  sigaction(SIGTERM, &sa, 0);  
1042    
1043   setbuf(stdout, NULL);   setbuf(stdout, NULL);
1044    
1045   parse_args(argc, argv);   parse_args(argv);
1046    
1047   if (!notitle)   if (!notitle)
1048   puts("fsck (busybox "BB_VER", "BB_BT")");   puts("fsck (busybox "BB_VER", "BB_BT")");
# Line 1200  int fsck_main(int argc, char *argv[]) Line 1054  int fsck_main(int argc, char *argv[])
1054   fstab = "/etc/fstab";   fstab = "/etc/fstab";
1055   load_fs_info(fstab);   load_fs_info(fstab);
1056    
1057   interactive = (num_devices == 1) | serialize;   /*interactive = (num_devices == 1) | serialize;*/
1058    
1059   /* If -A was specified ("check all"), do that! */   if (num_devices == 0)
1060     /*interactive =*/ serialize = doall = 1;
1061   if (doall)   if (doall)
1062   return check_all();   return check_all();
1063    
1064   if (num_devices == 0) {   status = 0;
  serialize = 1;  
  interactive = 1;  
  return check_all();  
  }  
   
1065   for (i = 0; i < num_devices; i++) {   for (i = 0; i < num_devices; i++) {
1066   if (cancel_requested) {   if (cancel_requested) {
1067   kill_all_if_cancel_requested();   kill_all_if_cancel_requested();
# Line 1220  int fsck_main(int argc, char *argv[]) Line 1070  int fsck_main(int argc, char *argv[])
1070    
1071   fs = lookup(devices[i]);   fs = lookup(devices[i]);
1072   if (!fs)   if (!fs)
1073   fs = create_fs_device(devices[i], 0, "auto", 0, -1, -1);   fs = create_fs_device(devices[i], "", "auto", NULL, -1);
1074   fsck_device(fs, interactive);   fsck_device(fs /*, interactive */);
1075    
1076   if (serialize   if (serialize
1077   || (max_running && (num_running >= max_running))   || (max_running && (num_running >= max_running))
1078   ) {   ) {
1079   struct fsck_instance *inst;   int exit_status = wait_one(0);
1080     if (exit_status >= 0)
1081   inst = wait_one(0);   status |= exit_status;
  if (inst) {  
  status |= inst->exit_status;  
  free_instance(inst);  
  }  
1082   if (verbose > 1)   if (verbose > 1)
1083   puts("----------------------------------");   puts("----------------------------------");
1084   }   }

Legend:
Removed from v.532  
changed lines
  Added in v.816