Magellan Linux

Annotation of /trunk/mkinitrd-magellan/busybox/e2fsprogs/old_e2fsprogs/fsck.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 984 - (hide annotations) (download)
Sun May 30 11:32:42 2010 UTC (14 years ago) by niro
File MIME type: text/plain
File size: 28460 byte(s)
-updated to busybox-1.16.1 and enabled blkid/uuid support in default config
1 niro 532 /* vi: set sw=4 ts=4: */
2     /*
3     * pfsck --- A generic, parallelizing front-end for the fsck program.
4     * It will automatically try to run fsck programs in parallel if the
5     * devices are on separate spindles. It is based on the same ideas as
6     * the generic front end for fsck by David Engel and Fred van Kempen,
7     * but it has been completely rewritten from scratch to support
8     * parallel execution.
9     *
10     * Written by Theodore Ts'o, <tytso@mit.edu>
11     *
12     * Miquel van Smoorenburg (miquels@drinkel.ow.org) 20-Oct-1994:
13     * o Changed -t fstype to behave like with mount when -A (all file
14     * systems) or -M (like mount) is specified.
15     * o fsck looks if it can find the fsck.type program to decide
16     * if it should ignore the fs type. This way more fsck programs
17     * can be added without changing this front-end.
18     * o -R flag skip root file system.
19     *
20     * Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
21     * 2001, 2002, 2003, 2004, 2005 by Theodore Ts'o.
22     *
23 niro 984 * Licensed under GPLv2, see file LICENSE in this tarball for details.
24 niro 532 */
25    
26     #include <sys/types.h>
27     #include <sys/wait.h>
28     #include <sys/stat.h>
29     #include <limits.h>
30     #include <stdio.h>
31     #include <ctype.h>
32     #include <string.h>
33     #include <time.h>
34     #include <stdlib.h>
35     #include <errno.h>
36     #include <paths.h>
37     #include <unistd.h>
38     #include <errno.h>
39     #include <signal.h>
40    
41     #include "fsck.h"
42     #include "blkid/blkid.h"
43    
44     #include "e2fsbb.h"
45    
46 niro 816 #include "libbb.h"
47 niro 532
48     #ifndef _PATH_MNTTAB
49     #define _PATH_MNTTAB "/etc/fstab"
50     #endif
51    
52     /*
53     * fsck.h
54     */
55    
56     #ifndef DEFAULT_FSTYPE
57     #define DEFAULT_FSTYPE "ext2"
58     #endif
59    
60     #define MAX_DEVICES 32
61     #define MAX_ARGS 32
62    
63     /*
64     * Internal structure for mount tabel entries.
65     */
66    
67     struct fs_info {
68     char *device;
69     char *mountpt;
70     char *type;
71     char *opts;
72     int freq;
73     int passno;
74     int flags;
75     struct fs_info *next;
76     };
77    
78     #define FLAG_DONE 1
79     #define FLAG_PROGRESS 2
80    
81     /*
82     * Structure to allow exit codes to be stored
83     */
84     struct fsck_instance {
85     int pid;
86     int flags;
87     int exit_status;
88     time_t start_time;
89     char * prog;
90     char * type;
91     char * device;
92     char * base_device;
93     struct fsck_instance *next;
94     };
95    
96     /*
97     * base_device.c
98     *
99     * Return the "base device" given a particular device; this is used to
100     * assure that we only fsck one partition on a particular drive at any
101     * one time. Otherwise, the disk heads will be seeking all over the
102     * place. If the base device cannot be determined, return NULL.
103     *
104     * The base_device() function returns an allocated string which must
105     * be freed.
106     *
107     */
108    
109    
110     #ifdef CONFIG_FEATURE_DEVFS
111     /*
112     * Required for the uber-silly devfs /dev/ide/host1/bus2/target3/lun3
113     * pathames.
114     */
115 niro 816 static const char *const devfs_hier[] = {
116 niro 532 "host", "bus", "target", "lun", 0
117     };
118     #endif
119    
120     static char *base_device(const char *device)
121     {
122     char *str, *cp;
123     #ifdef CONFIG_FEATURE_DEVFS
124 niro 816 const char *const *hier;
125 niro 532 const char *disk;
126     int len;
127     #endif
128    
129     cp = str = xstrdup(device);
130    
131     /* Skip over /dev/; if it's not present, give up. */
132     if (strncmp(cp, "/dev/", 5) != 0)
133     goto errout;
134     cp += 5;
135    
136     /*
137     * For md devices, we treat them all as if they were all
138     * on one disk, since we don't know how to parallelize them.
139     */
140     if (cp[0] == 'm' && cp[1] == 'd') {
141     *(cp+2) = 0;
142     return str;
143     }
144    
145     /* Handle DAC 960 devices */
146     if (strncmp(cp, "rd/", 3) == 0) {
147     cp += 3;
148     if (cp[0] != 'c' || cp[2] != 'd' ||
149     !isdigit(cp[1]) || !isdigit(cp[3]))
150     goto errout;
151     *(cp+4) = 0;
152     return str;
153     }
154    
155     /* Now let's handle /dev/hd* and /dev/sd* devices.... */
156     if ((cp[0] == 'h' || cp[0] == 's') && (cp[1] == 'd')) {
157     cp += 2;
158     /* If there's a single number after /dev/hd, skip it */
159     if (isdigit(*cp))
160     cp++;
161     /* What follows must be an alpha char, or give up */
162     if (!isalpha(*cp))
163     goto errout;
164     *(cp + 1) = 0;
165     return str;
166     }
167    
168     #ifdef CONFIG_FEATURE_DEVFS
169     /* Now let's handle devfs (ugh) names */
170     len = 0;
171     if (strncmp(cp, "ide/", 4) == 0)
172     len = 4;
173     if (strncmp(cp, "scsi/", 5) == 0)
174     len = 5;
175     if (len) {
176     cp += len;
177     /*
178     * Now we proceed down the expected devfs hierarchy.
179     * i.e., .../host1/bus2/target3/lun4/...
180     * If we don't find the expected token, followed by
181     * some number of digits at each level, abort.
182     */
183     for (hier = devfs_hier; *hier; hier++) {
184     len = strlen(*hier);
185     if (strncmp(cp, *hier, len) != 0)
186     goto errout;
187     cp += len;
188     while (*cp != '/' && *cp != 0) {
189     if (!isdigit(*cp))
190     goto errout;
191     cp++;
192     }
193     cp++;
194     }
195     *(cp - 1) = 0;
196     return str;
197     }
198    
199     /* Now handle devfs /dev/disc or /dev/disk names */
200     disk = 0;
201     if (strncmp(cp, "discs/", 6) == 0)
202     disk = "disc";
203     else if (strncmp(cp, "disks/", 6) == 0)
204     disk = "disk";
205     if (disk) {
206     cp += 6;
207     if (strncmp(cp, disk, 4) != 0)
208     goto errout;
209     cp += 4;
210     while (*cp != '/' && *cp != 0) {
211     if (!isdigit(*cp))
212     goto errout;
213     cp++;
214     }
215     *cp = 0;
216     return str;
217     }
218     #endif
219    
220     errout:
221     free(str);
222     return NULL;
223     }
224    
225    
226 niro 816 static const char *const ignored_types[] = {
227 niro 532 "ignore",
228     "iso9660",
229     "nfs",
230     "proc",
231     "sw",
232     "swap",
233     "tmpfs",
234     "devpts",
235     NULL
236     };
237    
238 niro 816 static const char *const really_wanted[] = {
239 niro 532 "minix",
240     "ext2",
241     "ext3",
242     "jfs",
243     "reiserfs",
244     "xiafs",
245     "xfs",
246     NULL
247     };
248    
249     #define BASE_MD "/dev/md"
250    
251     /*
252     * Global variables for options
253     */
254     static char *devices[MAX_DEVICES];
255     static char *args[MAX_ARGS];
256     static int num_devices, num_args;
257    
258     static int verbose;
259     static int doall;
260     static int noexecute;
261     static int serialize;
262     static int skip_root;
263     static int like_mount;
264     static int notitle;
265     static int parallel_root;
266     static int progress;
267     static int progress_fd;
268     static int force_all_parallel;
269     static int num_running;
270     static int max_running;
271     static volatile int cancel_requested;
272     static int kill_sent;
273     static char *fstype;
274     static struct fs_info *filesys_info, *filesys_last;
275     static struct fsck_instance *instance_list;
276     static char *fsck_path;
277     static blkid_cache cache;
278    
279     static char *string_copy(const char *s)
280     {
281     char *ret;
282    
283     if (!s)
284     return 0;
285 niro 816 ret = xstrdup(s);
286 niro 532 return ret;
287     }
288    
289     static int string_to_int(const char *s)
290     {
291     long l;
292     char *p;
293    
294     l = strtol(s, &p, 0);
295     if (*p || l == LONG_MIN || l == LONG_MAX || l < 0 || l > INT_MAX)
296     return -1;
297     else
298     return (int) l;
299     }
300    
301     static char *skip_over_blank(char *cp)
302     {
303     while (*cp && isspace(*cp))
304     cp++;
305     return cp;
306     }
307    
308     static char *skip_over_word(char *cp)
309     {
310     while (*cp && !isspace(*cp))
311     cp++;
312     return cp;
313     }
314    
315     static void strip_line(char *line)
316     {
317     char *p;
318    
319     while (*line) {
320     p = line + strlen(line) - 1;
321     if ((*p == '\n') || (*p == '\r'))
322     *p = 0;
323     else
324     break;
325     }
326     }
327    
328     static char *parse_word(char **buf)
329     {
330     char *word, *next;
331    
332     word = *buf;
333     if (*word == 0)
334     return 0;
335    
336     word = skip_over_blank(word);
337     next = skip_over_word(word);
338     if (*next)
339     *next++ = 0;
340     *buf = next;
341     return word;
342     }
343    
344     static void parse_escape(char *word)
345     {
346     char *q, c;
347     const char *p;
348    
349     if (!word)
350     return;
351    
352     for (p = q = word; *p; q++) {
353     c = *p++;
354     if (c != '\\') {
355     *q = c;
356     } else {
357     *q = bb_process_escape_sequence(&p);
358     }
359     }
360     *q = 0;
361     }
362    
363     static void free_instance(struct fsck_instance *i)
364     {
365     if (i->prog)
366     free(i->prog);
367     if (i->device)
368     free(i->device);
369     if (i->base_device)
370     free(i->base_device);
371     free(i);
372     }
373    
374     static struct fs_info *create_fs_device(const char *device, const char *mntpnt,
375     const char *type, const char *opts,
376     int freq, int passno)
377     {
378     struct fs_info *fs;
379    
380 niro 984 fs = xmalloc(sizeof(struct fs_info));
381 niro 532
382     fs->device = string_copy(device);
383     fs->mountpt = string_copy(mntpnt);
384     fs->type = string_copy(type);
385     fs->opts = string_copy(opts ? opts : "");
386     fs->freq = freq;
387     fs->passno = passno;
388     fs->flags = 0;
389     fs->next = NULL;
390    
391     if (!filesys_info)
392     filesys_info = fs;
393     else
394     filesys_last->next = fs;
395     filesys_last = fs;
396    
397     return fs;
398     }
399    
400    
401    
402     static int parse_fstab_line(char *line, struct fs_info **ret_fs)
403     {
404     char *dev, *device, *mntpnt, *type, *opts, *freq, *passno, *cp;
405     struct fs_info *fs;
406    
407     *ret_fs = 0;
408     strip_line(line);
409     if ((cp = strchr(line, '#')))
410     *cp = 0; /* Ignore everything after the comment char */
411     cp = line;
412    
413     device = parse_word(&cp);
414     mntpnt = parse_word(&cp);
415     type = parse_word(&cp);
416     opts = parse_word(&cp);
417     freq = parse_word(&cp);
418     passno = parse_word(&cp);
419    
420     if (!device)
421     return 0; /* Allow blank lines */
422    
423     if (!mntpnt || !type)
424     return -1;
425    
426     parse_escape(device);
427     parse_escape(mntpnt);
428     parse_escape(type);
429     parse_escape(opts);
430     parse_escape(freq);
431     parse_escape(passno);
432    
433     dev = blkid_get_devname(cache, device, NULL);
434     if (dev)
435     device = dev;
436    
437     if (strchr(type, ','))
438     type = 0;
439    
440     fs = create_fs_device(device, mntpnt, type ? type : "auto", opts,
441     freq ? atoi(freq) : -1,
442     passno ? atoi(passno) : -1);
443     if (dev)
444     free(dev);
445    
446     if (!fs)
447     return -1;
448     *ret_fs = fs;
449     return 0;
450     }
451    
452     static void interpret_type(struct fs_info *fs)
453     {
454     char *t;
455    
456     if (strcmp(fs->type, "auto") != 0)
457     return;
458     t = blkid_get_tag_value(cache, "TYPE", fs->device);
459     if (t) {
460     free(fs->type);
461     fs->type = t;
462     }
463     }
464    
465     /*
466     * Load the filesystem database from /etc/fstab
467     */
468     static void load_fs_info(const char *filename)
469     {
470     FILE *f;
471     char buf[1024];
472     int lineno = 0;
473     int old_fstab = 1;
474     struct fs_info *fs;
475    
476 niro 816 if ((f = fopen_or_warn(filename, "r")) == NULL) {
477 niro 532 return;
478     }
479     while (!feof(f)) {
480     lineno++;
481     if (!fgets(buf, sizeof(buf), f))
482     break;
483     buf[sizeof(buf)-1] = 0;
484     if (parse_fstab_line(buf, &fs) < 0) {
485     bb_error_msg("WARNING: bad format "
486     "on line %d of %s\n", lineno, filename);
487     continue;
488     }
489     if (!fs)
490     continue;
491     if (fs->passno < 0)
492     fs->passno = 0;
493     else
494     old_fstab = 0;
495     }
496    
497     fclose(f);
498    
499     if (old_fstab) {
500     fputs("\007\007\007"
501     "WARNING: Your /etc/fstab does not contain the fsck passno\n"
502     " field. I will kludge around things for you, but you\n"
503     " should fix your /etc/fstab file as soon as you can.\n\n", stderr);
504    
505     for (fs = filesys_info; fs; fs = fs->next) {
506     fs->passno = 1;
507     }
508     }
509     }
510    
511     /* Lookup filesys in /etc/fstab and return the corresponding entry. */
512     static struct fs_info *lookup(char *filesys)
513     {
514     struct fs_info *fs;
515    
516     /* No filesys name given. */
517     if (filesys == NULL)
518     return NULL;
519    
520     for (fs = filesys_info; fs; fs = fs->next) {
521     if (!strcmp(filesys, fs->device) ||
522     (fs->mountpt && !strcmp(filesys, fs->mountpt)))
523     break;
524     }
525    
526     return fs;
527     }
528    
529     /* Find fsck program for a given fs type. */
530     static char *find_fsck(char *type)
531     {
532 niro 816 char *s;
533     const char *tpl;
534     char *p = string_copy(fsck_path);
535     struct stat st;
536 niro 532
537 niro 816 /* Are we looking for a program or just a type? */
538     tpl = (strncmp(type, "fsck.", 5) ? "%s/fsck.%s" : "%s/%s");
539 niro 532
540 niro 816 for (s = strtok(p, ":"); s; s = strtok(NULL, ":")) {
541     s = xasprintf(tpl, s, type);
542     if (stat(s, &st) == 0) break;
543     free(s);
544     }
545     free(p);
546     return s;
547 niro 532 }
548    
549     static int progress_active(void)
550     {
551     struct fsck_instance *inst;
552    
553     for (inst = instance_list; inst; inst = inst->next) {
554     if (inst->flags & FLAG_DONE)
555     continue;
556     if (inst->flags & FLAG_PROGRESS)
557     return 1;
558     }
559     return 0;
560     }
561    
562     /*
563     * Execute a particular fsck program, and link it into the list of
564     * child processes we are waiting for.
565     */
566     static int execute(const char *type, const char *device, const char *mntpt,
567     int interactive)
568     {
569     char *s, *argv[80];
570     char *prog;
571     int argc, i;
572     struct fsck_instance *inst, *p;
573     pid_t pid;
574    
575 niro 984 inst = xzalloc(sizeof(struct fsck_instance));
576 niro 532
577     prog = xasprintf("fsck.%s", type);
578     argv[0] = prog;
579     argc = 1;
580    
581     for (i=0; i <num_args; i++)
582     argv[argc++] = string_copy(args[i]);
583    
584     if (progress && !progress_active()) {
585     if ((strcmp(type, "ext2") == 0) ||
586     (strcmp(type, "ext3") == 0)) {
587     char tmp[80];
588     snprintf(tmp, 80, "-C%d", progress_fd);
589     argv[argc++] = string_copy(tmp);
590     inst->flags |= FLAG_PROGRESS;
591     }
592     }
593    
594     argv[argc++] = string_copy(device);
595     argv[argc] = 0;
596    
597     s = find_fsck(prog);
598     if (s == NULL) {
599     bb_error_msg("%s: not found", prog);
600     return ENOENT;
601     }
602    
603     if (verbose || noexecute) {
604     printf("[%s (%d) -- %s] ", s, num_running,
605     mntpt ? mntpt : device);
606     for (i=0; i < argc; i++)
607     printf("%s ", argv[i]);
608 niro 816 bb_putchar('\n');
609 niro 532 }
610    
611     /* Fork and execute the correct program. */
612     if (noexecute)
613     pid = -1;
614     else if ((pid = fork()) < 0) {
615     perror("fork");
616     return errno;
617     } else if (pid == 0) {
618     if (!interactive)
619     close(0);
620     (void) execv(s, argv);
621 niro 816 bb_simple_perror_msg_and_die(argv[0]);
622 niro 532 }
623    
624     for (i = 1; i < argc; i++)
625     free(argv[i]);
626    
627     free(s);
628     inst->pid = pid;
629     inst->prog = prog;
630     inst->type = string_copy(type);
631     inst->device = string_copy(device);
632     inst->base_device = base_device(device);
633     inst->start_time = time(0);
634     inst->next = NULL;
635    
636     /*
637     * Find the end of the list, so we add the instance on at the end.
638     */
639     for (p = instance_list; p && p->next; p = p->next);
640    
641     if (p)
642     p->next = inst;
643     else
644     instance_list = inst;
645    
646     return 0;
647     }
648    
649     /*
650     * Send a signal to all outstanding fsck child processes
651     */
652     static int kill_all(int signum)
653     {
654     struct fsck_instance *inst;
655     int n = 0;
656    
657     for (inst = instance_list; inst; inst = inst->next) {
658     if (inst->flags & FLAG_DONE)
659     continue;
660     kill(inst->pid, signum);
661     n++;
662     }
663     return n;
664     }
665    
666     /*
667     * Wait for one child process to exit; when it does, unlink it from
668     * the list of executing child processes, and return it.
669     */
670     static struct fsck_instance *wait_one(int flags)
671     {
672     int status;
673     int sig;
674     struct fsck_instance *inst, *inst2, *prev;
675     pid_t pid;
676    
677     if (!instance_list)
678     return NULL;
679    
680     if (noexecute) {
681     inst = instance_list;
682     prev = 0;
683     #ifdef RANDOM_DEBUG
684     while (inst->next && (random() & 1)) {
685     prev = inst;
686     inst = inst->next;
687     }
688     #endif
689     inst->exit_status = 0;
690     goto ret_inst;
691     }
692    
693     /*
694     * gcc -Wall fails saving throw against stupidity
695     * (inst and prev are thought to be uninitialized variables)
696     */
697     inst = prev = NULL;
698    
699     do {
700     pid = waitpid(-1, &status, flags);
701     if (cancel_requested && !kill_sent) {
702     kill_all(SIGTERM);
703     kill_sent++;
704     }
705     if ((pid == 0) && (flags & WNOHANG))
706     return NULL;
707     if (pid < 0) {
708     if ((errno == EINTR) || (errno == EAGAIN))
709     continue;
710     if (errno == ECHILD) {
711     bb_error_msg("wait: no more child process?!?");
712     return NULL;
713     }
714     perror("wait");
715     continue;
716     }
717     for (prev = 0, inst = instance_list;
718     inst;
719     prev = inst, inst = inst->next) {
720     if (inst->pid == pid)
721     break;
722     }
723     } while (!inst);
724    
725     if (WIFEXITED(status))
726     status = WEXITSTATUS(status);
727     else if (WIFSIGNALED(status)) {
728     sig = WTERMSIG(status);
729     if (sig == SIGINT) {
730     status = EXIT_UNCORRECTED;
731     } else {
732     printf("Warning... %s for device %s exited "
733     "with signal %d.\n",
734     inst->prog, inst->device, sig);
735     status = EXIT_ERROR;
736     }
737     } else {
738     printf("%s %s: status is %x, should never happen.\n",
739     inst->prog, inst->device, status);
740     status = EXIT_ERROR;
741     }
742     inst->exit_status = status;
743     if (progress && (inst->flags & FLAG_PROGRESS) &&
744     !progress_active()) {
745     for (inst2 = instance_list; inst2; inst2 = inst2->next) {
746     if (inst2->flags & FLAG_DONE)
747     continue;
748     if (strcmp(inst2->type, "ext2") &&
749     strcmp(inst2->type, "ext3"))
750     continue;
751     /*
752     * If we've just started the fsck, wait a tiny
753     * bit before sending the kill, to give it
754     * time to set up the signal handler
755     */
756     if (inst2->start_time < time(0)+2) {
757     if (fork() == 0) {
758     sleep(1);
759     kill(inst2->pid, SIGUSR1);
760     exit(0);
761     }
762     } else
763     kill(inst2->pid, SIGUSR1);
764     inst2->flags |= FLAG_PROGRESS;
765     break;
766     }
767     }
768     ret_inst:
769     if (prev)
770     prev->next = inst->next;
771     else
772     instance_list = inst->next;
773     if (verbose > 1)
774     printf("Finished with %s (exit status %d)\n",
775     inst->device, inst->exit_status);
776     num_running--;
777     return inst;
778     }
779    
780     #define FLAG_WAIT_ALL 0
781     #define FLAG_WAIT_ATLEAST_ONE 1
782     /*
783     * Wait until all executing child processes have exited; return the
784     * logical OR of all of their exit code values.
785     */
786     static int wait_many(int flags)
787     {
788     struct fsck_instance *inst;
789     int global_status = 0;
790     int wait_flags = 0;
791    
792     while ((inst = wait_one(wait_flags))) {
793     global_status |= inst->exit_status;
794     free_instance(inst);
795     #ifdef RANDOM_DEBUG
796     if (noexecute && (flags & WNOHANG) && !(random() % 3))
797     break;
798     #endif
799     if (flags & FLAG_WAIT_ATLEAST_ONE)
800     wait_flags = WNOHANG;
801     }
802     return global_status;
803     }
804    
805     /*
806     * Run the fsck program on a particular device
807     *
808     * If the type is specified using -t, and it isn't prefixed with "no"
809     * (as in "noext2") and only one filesystem type is specified, then
810     * use that type regardless of what is specified in /etc/fstab.
811     *
812     * If the type isn't specified by the user, then use either the type
813     * specified in /etc/fstab, or DEFAULT_FSTYPE.
814     */
815     static void fsck_device(struct fs_info *fs, int interactive)
816     {
817     const char *type;
818     int retval;
819    
820     interpret_type(fs);
821    
822     if (strcmp(fs->type, "auto") != 0)
823     type = fs->type;
824     else if (fstype && strncmp(fstype, "no", 2) &&
825     strncmp(fstype, "opts=", 5) && strncmp(fstype, "loop", 4) &&
826     !strchr(fstype, ','))
827     type = fstype;
828     else
829     type = DEFAULT_FSTYPE;
830    
831     num_running++;
832     retval = execute(type, fs->device, fs->mountpt, interactive);
833     if (retval) {
834     bb_error_msg("error %d while executing fsck.%s for %s",
835     retval, type, fs->device);
836     num_running--;
837     }
838     }
839    
840    
841     /*
842     * Deal with the fsck -t argument.
843     */
844     struct fs_type_compile {
845     char **list;
846     int *type;
847     int negate;
848     } fs_type_compiled;
849    
850     #define FS_TYPE_NORMAL 0
851     #define FS_TYPE_OPT 1
852     #define FS_TYPE_NEGOPT 2
853    
854     static const char fs_type_syntax_error[] =
855     "Either all or none of the filesystem types passed to -t must be prefixed\n"
856     "with 'no' or '!'.";
857    
858     static void compile_fs_type(char *fs_type, struct fs_type_compile *cmp)
859     {
860     char *cp, *list, *s;
861     int num = 2;
862     int negate, first_negate = 1;
863    
864     if (fs_type) {
865     for (cp=fs_type; *cp; cp++) {
866     if (*cp == ',')
867     num++;
868     }
869     }
870    
871     cmp->list = xzalloc(num * sizeof(char *));
872     cmp->type = xzalloc(num * sizeof(int));
873     cmp->negate = 0;
874    
875     if (!fs_type)
876     return;
877    
878     list = string_copy(fs_type);
879     num = 0;
880     s = strtok(list, ",");
881 niro 816 while (s) {
882 niro 532 negate = 0;
883     if (strncmp(s, "no", 2) == 0) {
884     s += 2;
885     negate = 1;
886     } else if (*s == '!') {
887     s++;
888     negate = 1;
889     }
890     if (strcmp(s, "loop") == 0)
891     /* loop is really short-hand for opts=loop */
892     goto loop_special_case;
893     else if (strncmp(s, "opts=", 5) == 0) {
894     s += 5;
895     loop_special_case:
896     cmp->type[num] = negate ? FS_TYPE_NEGOPT : FS_TYPE_OPT;
897     } else {
898     if (first_negate) {
899     cmp->negate = negate;
900     first_negate = 0;
901     }
902     if ((negate && !cmp->negate) ||
903     (!negate && cmp->negate)) {
904     bb_error_msg_and_die("%s", fs_type_syntax_error);
905     }
906     }
907     cmp->list[num++] = string_copy(s);
908     s = strtok(NULL, ",");
909     }
910     free(list);
911     }
912    
913     /*
914     * This function returns true if a particular option appears in a
915     * comma-delimited options list
916     */
917     static int opt_in_list(char *opt, char *optlist)
918     {
919     char *list, *s;
920    
921     if (!optlist)
922     return 0;
923     list = string_copy(optlist);
924    
925     s = strtok(list, ",");
926 niro 816 while (s) {
927 niro 532 if (strcmp(s, opt) == 0) {
928     free(list);
929     return 1;
930     }
931     s = strtok(NULL, ",");
932     }
933     free(list);
934     return 0;
935     }
936    
937     /* See if the filesystem matches the criteria given by the -t option */
938     static int fs_match(struct fs_info *fs, struct fs_type_compile *cmp)
939     {
940     int n, ret = 0, checked_type = 0;
941     char *cp;
942    
943     if (cmp->list == 0 || cmp->list[0] == 0)
944     return 1;
945    
946     for (n=0; (cp = cmp->list[n]); n++) {
947     switch (cmp->type[n]) {
948     case FS_TYPE_NORMAL:
949     checked_type++;
950     if (strcmp(cp, fs->type) == 0) {
951     ret = 1;
952     }
953     break;
954     case FS_TYPE_NEGOPT:
955     if (opt_in_list(cp, fs->opts))
956     return 0;
957     break;
958     case FS_TYPE_OPT:
959     if (!opt_in_list(cp, fs->opts))
960     return 0;
961     break;
962     }
963     }
964     if (checked_type == 0)
965     return 1;
966     return (cmp->negate ? !ret : ret);
967     }
968    
969     /* Check if we should ignore this filesystem. */
970     static int ignore(struct fs_info *fs)
971     {
972     int wanted;
973     char *s;
974    
975     /*
976     * If the pass number is 0, ignore it.
977     */
978     if (fs->passno == 0)
979     return 1;
980    
981     interpret_type(fs);
982    
983     /*
984     * If a specific fstype is specified, and it doesn't match,
985     * ignore it.
986     */
987     if (!fs_match(fs, &fs_type_compiled)) return 1;
988    
989     /* Are we ignoring this type? */
990     if (index_in_str_array(ignored_types, fs->type) >= 0)
991     return 1;
992    
993     /* Do we really really want to check this fs? */
994     wanted = index_in_str_array(really_wanted, fs->type) >= 0;
995    
996     /* See if the <fsck.fs> program is available. */
997     s = find_fsck(fs->type);
998     if (s == NULL) {
999     if (wanted)
1000 niro 984 bb_error_msg("can't check %s: fsck.%s not found",
1001 niro 532 fs->device, fs->type);
1002     return 1;
1003     }
1004     free(s);
1005    
1006     /* We can and want to check this file system type. */
1007     return 0;
1008     }
1009    
1010     /*
1011     * Returns TRUE if a partition on the same disk is already being
1012     * checked.
1013     */
1014     static int device_already_active(char *device)
1015     {
1016     struct fsck_instance *inst;
1017     char *base;
1018    
1019     if (force_all_parallel)
1020     return 0;
1021    
1022     #ifdef BASE_MD
1023     /* Don't check a soft raid disk with any other disk */
1024     if (instance_list &&
1025     (!strncmp(instance_list->device, BASE_MD, sizeof(BASE_MD)-1) ||
1026     !strncmp(device, BASE_MD, sizeof(BASE_MD)-1)))
1027     return 1;
1028     #endif
1029    
1030     base = base_device(device);
1031     /*
1032     * If we don't know the base device, assume that the device is
1033     * already active if there are any fsck instances running.
1034     */
1035     if (!base)
1036     return (instance_list != 0);
1037     for (inst = instance_list; inst; inst = inst->next) {
1038     if (!inst->base_device || !strcmp(base, inst->base_device)) {
1039     free(base);
1040     return 1;
1041     }
1042     }
1043     free(base);
1044     return 0;
1045     }
1046    
1047     /* Check all file systems, using the /etc/fstab table. */
1048     static int check_all(void)
1049     {
1050     struct fs_info *fs = NULL;
1051     int status = EXIT_OK;
1052     int not_done_yet = 1;
1053     int passno = 1;
1054     int pass_done;
1055    
1056     if (verbose)
1057     fputs("Checking all file systems.\n", stdout);
1058    
1059     /*
1060     * Do an initial scan over the filesystem; mark filesystems
1061     * which should be ignored as done, and resolve any "auto"
1062     * filesystem types (done as a side-effect of calling ignore()).
1063     */
1064     for (fs = filesys_info; fs; fs = fs->next) {
1065     if (ignore(fs))
1066     fs->flags |= FLAG_DONE;
1067     }
1068    
1069     /*
1070     * Find and check the root filesystem.
1071     */
1072     if (!parallel_root) {
1073     for (fs = filesys_info; fs; fs = fs->next) {
1074     if (LONE_CHAR(fs->mountpt, '/'))
1075     break;
1076     }
1077     if (fs) {
1078     if (!skip_root && !ignore(fs)) {
1079     fsck_device(fs, 1);
1080     status |= wait_many(FLAG_WAIT_ALL);
1081     if (status > EXIT_NONDESTRUCT)
1082     return status;
1083     }
1084     fs->flags |= FLAG_DONE;
1085     }
1086     }
1087     /*
1088     * This is for the bone-headed user who enters the root
1089     * filesystem twice. Skip root will skep all root entries.
1090     */
1091     if (skip_root)
1092     for (fs = filesys_info; fs; fs = fs->next)
1093     if (LONE_CHAR(fs->mountpt, '/'))
1094     fs->flags |= FLAG_DONE;
1095    
1096     while (not_done_yet) {
1097     not_done_yet = 0;
1098     pass_done = 1;
1099    
1100     for (fs = filesys_info; fs; fs = fs->next) {
1101     if (cancel_requested)
1102     break;
1103     if (fs->flags & FLAG_DONE)
1104     continue;
1105     /*
1106     * If the filesystem's pass number is higher
1107     * than the current pass number, then we don't
1108     * do it yet.
1109     */
1110     if (fs->passno > passno) {
1111     not_done_yet++;
1112     continue;
1113     }
1114     /*
1115     * If a filesystem on a particular device has
1116     * already been spawned, then we need to defer
1117     * this to another pass.
1118     */
1119     if (device_already_active(fs->device)) {
1120     pass_done = 0;
1121     continue;
1122     }
1123     /*
1124     * Spawn off the fsck process
1125     */
1126     fsck_device(fs, serialize);
1127     fs->flags |= FLAG_DONE;
1128    
1129     /*
1130     * Only do one filesystem at a time, or if we
1131     * have a limit on the number of fsck's extant
1132     * at one time, apply that limit.
1133     */
1134     if (serialize ||
1135     (max_running && (num_running >= max_running))) {
1136     pass_done = 0;
1137     break;
1138     }
1139     }
1140     if (cancel_requested)
1141     break;
1142     if (verbose > 1)
1143     printf("--waiting-- (pass %d)\n", passno);
1144     status |= wait_many(pass_done ? FLAG_WAIT_ALL :
1145     FLAG_WAIT_ATLEAST_ONE);
1146     if (pass_done) {
1147     if (verbose > 1)
1148     printf("----------------------------------\n");
1149     passno++;
1150     } else
1151     not_done_yet++;
1152     }
1153     if (cancel_requested && !kill_sent) {
1154     kill_all(SIGTERM);
1155     kill_sent++;
1156     }
1157     status |= wait_many(FLAG_WAIT_ATLEAST_ONE);
1158     return status;
1159     }
1160    
1161     static void signal_cancel(int sig FSCK_ATTR((unused)))
1162     {
1163     cancel_requested++;
1164     }
1165    
1166 niro 816 static void PRS(int argc, char **argv)
1167 niro 532 {
1168     int i, j;
1169     char *arg, *dev, *tmp = 0;
1170     char options[128];
1171     int opt = 0;
1172     int opts_for_fsck = 0;
1173     struct sigaction sa;
1174    
1175     /*
1176     * Set up signal action
1177     */
1178     memset(&sa, 0, sizeof(struct sigaction));
1179     sa.sa_handler = signal_cancel;
1180     sigaction(SIGINT, &sa, 0);
1181     sigaction(SIGTERM, &sa, 0);
1182    
1183     num_devices = 0;
1184     num_args = 0;
1185     instance_list = 0;
1186    
1187     for (i=1; i < argc; i++) {
1188     arg = argv[i];
1189     if (!arg)
1190     continue;
1191     if ((arg[0] == '/' && !opts_for_fsck) || strchr(arg, '=')) {
1192     if (num_devices >= MAX_DEVICES) {
1193     bb_error_msg_and_die("too many devices");
1194     }
1195     dev = blkid_get_devname(cache, arg, NULL);
1196     if (!dev && strchr(arg, '=')) {
1197     /*
1198     * Check to see if we failed because
1199     * /proc/partitions isn't found.
1200     */
1201     if (access("/proc/partitions", R_OK) < 0) {
1202 niro 984 bb_perror_msg_and_die("can't open /proc/partitions "
1203 niro 532 "(is /proc mounted?)");
1204     }
1205     /*
1206     * Check to see if this is because
1207     * we're not running as root
1208     */
1209     if (geteuid())
1210     bb_error_msg_and_die(
1211     "must be root to scan for matching filesystems: %s\n", arg);
1212     else
1213     bb_error_msg_and_die(
1214 niro 984 "can't find matching filesystem: %s", arg);
1215 niro 532 }
1216     devices[num_devices++] = dev ? dev : string_copy(arg);
1217     continue;
1218     }
1219     if (arg[0] != '-' || opts_for_fsck) {
1220     if (num_args >= MAX_ARGS) {
1221     bb_error_msg_and_die("too many arguments");
1222     }
1223     args[num_args++] = string_copy(arg);
1224     continue;
1225     }
1226     for (j=1; arg[j]; j++) {
1227     if (opts_for_fsck) {
1228     options[++opt] = arg[j];
1229     continue;
1230     }
1231     switch (arg[j]) {
1232     case 'A':
1233     doall++;
1234     break;
1235     case 'C':
1236     progress++;
1237     if (arg[j+1]) {
1238     progress_fd = string_to_int(arg+j+1);
1239     if (progress_fd < 0)
1240     progress_fd = 0;
1241     else
1242     goto next_arg;
1243     } else if ((i+1) < argc
1244     && argv[i+1][0] != '-') {
1245     progress_fd = string_to_int(argv[i]);
1246     if (progress_fd < 0)
1247     progress_fd = 0;
1248     else {
1249     goto next_arg;
1250     i++;
1251     }
1252     }
1253     break;
1254     case 'V':
1255     verbose++;
1256     break;
1257     case 'N':
1258     noexecute++;
1259     break;
1260     case 'R':
1261     skip_root++;
1262     break;
1263     case 'T':
1264     notitle++;
1265     break;
1266     case 'M':
1267     like_mount++;
1268     break;
1269     case 'P':
1270     parallel_root++;
1271     break;
1272     case 's':
1273     serialize++;
1274     break;
1275     case 't':
1276     tmp = 0;
1277     if (fstype)
1278     bb_show_usage();
1279     if (arg[j+1])
1280     tmp = arg+j+1;
1281     else if ((i+1) < argc)
1282     tmp = argv[++i];
1283     else
1284     bb_show_usage();
1285     fstype = string_copy(tmp);
1286     compile_fs_type(fstype, &fs_type_compiled);
1287     goto next_arg;
1288     case '-':
1289     opts_for_fsck++;
1290     break;
1291     case '?':
1292     bb_show_usage();
1293     break;
1294     default:
1295     options[++opt] = arg[j];
1296     break;
1297     }
1298     }
1299     next_arg:
1300     if (opt) {
1301     options[0] = '-';
1302     options[++opt] = '\0';
1303     if (num_args >= MAX_ARGS) {
1304     bb_error_msg("too many arguments");
1305     }
1306     args[num_args++] = string_copy(options);
1307     opt = 0;
1308     }
1309     }
1310     if (getenv("FSCK_FORCE_ALL_PARALLEL"))
1311     force_all_parallel++;
1312     if ((tmp = getenv("FSCK_MAX_INST")))
1313     max_running = atoi(tmp);
1314     }
1315    
1316 niro 816 int fsck_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
1317     int fsck_main(int argc, char **argv)
1318 niro 532 {
1319     int i, status = 0;
1320     int interactive = 0;
1321     const char *fstab;
1322     struct fs_info *fs;
1323    
1324     setvbuf(stdout, NULL, _IONBF, BUFSIZ);
1325     setvbuf(stderr, NULL, _IONBF, BUFSIZ);
1326    
1327     blkid_get_cache(&cache, NULL);
1328     PRS(argc, argv);
1329    
1330     if (!notitle)
1331     printf("fsck %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE);
1332    
1333     fstab = getenv("FSTAB_FILE");
1334     if (!fstab)
1335     fstab = _PATH_MNTTAB;
1336     load_fs_info(fstab);
1337    
1338     fsck_path = e2fs_set_sbin_path();
1339    
1340     if ((num_devices == 1) || (serialize))
1341     interactive = 1;
1342    
1343     /* If -A was specified ("check all"), do that! */
1344     if (doall)
1345     return check_all();
1346    
1347     if (num_devices == 0) {
1348     serialize++;
1349     interactive++;
1350     return check_all();
1351     }
1352 niro 816 for (i = 0; i < num_devices; i++) {
1353 niro 532 if (cancel_requested) {
1354     if (!kill_sent) {
1355     kill_all(SIGTERM);
1356     kill_sent++;
1357     }
1358     break;
1359     }
1360     fs = lookup(devices[i]);
1361     if (!fs) {
1362     fs = create_fs_device(devices[i], 0, "auto",
1363     0, -1, -1);
1364     if (!fs)
1365     continue;
1366     }
1367     fsck_device(fs, interactive);
1368     if (serialize ||
1369     (max_running && (num_running >= max_running))) {
1370     struct fsck_instance *inst;
1371    
1372     inst = wait_one(0);
1373     if (inst) {
1374     status |= inst->exit_status;
1375     free_instance(inst);
1376     }
1377     if (verbose > 1)
1378     printf("----------------------------------\n");
1379     }
1380     }
1381     status |= wait_many(FLAG_WAIT_ALL);
1382     blkid_put_cache(cache);
1383     return status;
1384     }