Ignore:
Timestamp:
Nov 6, 2007, 11:01:53 AM (13 years ago)
Author:
Bruno Cornec
Message:
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod? silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian? keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René? Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

Location:
branches/stable/mindi-busybox/e2fsprogs
Files:
125 deleted
5 edited
5 copied

Legend:

Unmodified
Added
Removed
  • branches/stable/mindi-busybox/e2fsprogs/Config.in

    r821 r1770  
    66menu "Linux Ext2 FS Progs"
    77
    8 config CONFIG_CHATTR
     8config CHATTR
    99    bool "chattr"
    1010    default n
     
    1212      chattr changes the file attributes on a second extended file system.
    1313
    14 config CONFIG_E2FSCK
    15     bool "e2fsck"
    16     default n
    17     help
    18       e2fsck is used to check Linux second extended file systems (ext2fs).
    19       e2fsck also supports ext2 filesystems countaining a journal (ext3).
    20       The normal compat symlinks 'fsck.ext2' and 'fsck.ext3' are also
    21       provided.
     14### config E2FSCK
     15###     bool "e2fsck"
     16###     default n
     17###     help
     18###       e2fsck is used to check Linux second extended file systems (ext2fs).
     19###       e2fsck also supports ext2 filesystems countaining a journal (ext3).
     20###       The normal compat symlinks 'fsck.ext2' and 'fsck.ext3' are also
     21###       provided.
    2222
    23 config CONFIG_FSCK
     23config FSCK
    2424    bool "fsck"
    2525    default n
     
    2929      checkers (fsck.fstype) available under Linux.
    3030
    31 config CONFIG_LSATTR
     31config LSATTR
    3232    bool "lsattr"
    3333    default n
     
    3535      lsattr lists the file attributes on a second extended file system.
    3636
    37 config CONFIG_MKE2FS
    38     bool "mke2fs"
    39     default n
    40     help
    41       mke2fs is used to create an ext2/ext3 filesystem.  The normal compat
    42       symlinks 'mkfs.ext2' and 'mkfs.ext3' are also provided.
     37### config MKE2FS
     38###     bool "mke2fs"
     39###     default n
     40###     help
     41###       mke2fs is used to create an ext2/ext3 filesystem.  The normal compat
     42###       symlinks 'mkfs.ext2' and 'mkfs.ext3' are also provided.
    4343
    44 config CONFIG_TUNE2FS
    45     bool "tune2fs"
    46     default n
    47     help
    48       tune2fs allows the system administrator to adjust various tunable
    49       filesystem parameters on Linux ext2/ext3 filesystems.
     44### config TUNE2FS
     45###     bool "tune2fs"
     46###     default n
     47###     help
     48###       tune2fs allows the system administrator to adjust various tunable
     49###       filesystem parameters on Linux ext2/ext3 filesystems.
    5050
    51 config CONFIG_E2LABEL
    52     bool "e2label"
    53     default n
    54     depends on CONFIG_TUNE2FS
    55     help
    56       e2label will display or change the filesystem label on the ext2
    57       filesystem located on device.
     51### config E2LABEL
     52###     bool "e2label"
     53###     default n
     54###     depends on TUNE2FS
     55###     help
     56###       e2label will display or change the filesystem label on the ext2
     57###       filesystem located on device.
    5858
    59 config CONFIG_FINDFS
    60     bool "findfs"
    61     default n
    62     depends on CONFIG_TUNE2FS
    63     help
    64       findfs will search the disks in the system looking for a filesystem
    65       which has a label matching label or a UUID equal to uuid.
     59### config FINDFS
     60###     bool "findfs"
     61###     default n
     62###     depends on TUNE2FS
     63###     help
     64###       findfs will search the disks in the system looking for a filesystem
     65###       which has a label matching label or a UUID equal to uuid.
    6666
    6767endmenu
  • branches/stable/mindi-busybox/e2fsprogs/README

    r821 r1770  
    1 This is a pretty straight rip from the e2fsprogs pkg.
     1Authors and contributors of original e2fsprogs:
    22
    3 See README's in subdirs for specific info.
     3Remy Card <card@masi.ibp.fr>
     4Theodore Ts'o <tytso@mit.edu>
     5Stephen C. Tweedie <sct@redhat.com>
     6Andreas Gruenbacher, <a.gruenbacher@computer.org>
     7Kaz Kylheku <kaz@ashi.footprints.net>
     8F.W. ten Wolde <franky@duteca.et.tudelft.nl>
     9Jeremy Fitzhardinge <jeremy@zip.com.au>
     10M.J.E. Mol <marcel@duteca.et.tudelft.nl>
     11Miquel van Smoorenburg <miquels@drinkel.ow.org>
     12Uwe Ohse <uwe@tirka.gun.de>
  • branches/stable/mindi-busybox/e2fsprogs/chattr.c

    r821 r1770  
     1/* vi: set sw=4 ts=4: */
    12/*
    23 * chattr.c     - Change file attributes on an ext2 file system
     
    1920 */
    2021
    21 #include <sys/types.h>
    22 #include <dirent.h>
    23 #include <fcntl.h>
    24 #include <stdio.h>
    25 #include <stdlib.h>
    26 #include <unistd.h>
    27 #include <string.h>
    28 #include <errno.h>
    29 #include <sys/param.h>
    30 #include <sys/stat.h>
    31 #include "ext2fs/ext2_fs.h"
    32 
    33 #ifdef __GNUC__
    34 # define EXT2FS_ATTR(x) __attribute__(x)
    35 #else
    36 # define EXT2FS_ATTR(x)
    37 #endif
    38 
    39 #include "e2fsbb.h"
    40 #include "e2p/e2p.h"
     22#include "libbb.h"
     23#include "e2fs_lib.h"
    4124
    4225#define OPT_ADD 1
     
    4427#define OPT_SET 4
    4528#define OPT_SET_VER 8
    46 static int flags;
    47 static int recursive;
    4829
    49 static unsigned long version;
    50 
    51 static unsigned long af;
    52 static unsigned long rf;
    53 static unsigned long sf;
    54 
    55 #ifdef CONFIG_LFS
    56 # define LSTAT lstat64
    57 # define STRUCT_STAT struct stat64
    58 #else
    59 # define LSTAT lstat
    60 # define STRUCT_STAT struct stat
    61 #endif
    62 
    63 struct flags_char {
    64     unsigned long flag;
    65     char optchar;
    66 };
    67 
    68 static const struct flags_char flags_array[] = {
    69     { EXT2_NOATIME_FL,      'A' },
    70     { EXT2_SYNC_FL,         'S' },
    71     { EXT2_DIRSYNC_FL,      'D' },
    72     { EXT2_APPEND_FL,       'a' },
    73     { EXT2_COMPR_FL,        'c' },
    74     { EXT2_NODUMP_FL,       'd' },
    75     { EXT2_IMMUTABLE_FL,    'i' },
    76     { EXT3_JOURNAL_DATA_FL, 'j' },
    77     { EXT2_SECRM_FL,        's' },
    78     { EXT2_UNRM_FL,         'u' },
    79     { EXT2_NOTAIL_FL,       't' },
    80     { EXT2_TOPDIR_FL,       'T' },
    81     { 0, 0 }
     30struct globals {
     31    unsigned long version;
     32    unsigned long af;
     33    unsigned long rf;
     34    smallint flags;
     35    smallint recursive;
    8236};
    8337
    8438static unsigned long get_flag(char c)
    8539{
    86     const struct flags_char *fp;
    87     for (fp = flags_array; fp->flag; fp++)
    88         if (fp->optchar == c)
    89             return fp->flag;
     40    /* Two separate vectors take less space than vector of structs */
     41    static const char flags_letter[] ALIGN1 = "ASDacdijsutT";
     42    static const unsigned long flags_val[] = {
     43        /* A */ EXT2_NOATIME_FL,
     44        /* S */ EXT2_SYNC_FL,
     45        /* D */ EXT2_DIRSYNC_FL,
     46        /* a */ EXT2_APPEND_FL,
     47        /* c */ EXT2_COMPR_FL,
     48        /* d */ EXT2_NODUMP_FL,
     49        /* i */ EXT2_IMMUTABLE_FL,
     50        /* j */ EXT3_JOURNAL_DATA_FL,
     51        /* s */ EXT2_SECRM_FL,
     52        /* u */ EXT2_UNRM_FL,
     53        /* t */ EXT2_NOTAIL_FL,
     54        /* T */ EXT2_TOPDIR_FL,
     55    };
     56    const char *fp;
     57
     58    for (fp = flags_letter; *fp; fp++)
     59        if (*fp == c)
     60            return flags_val[fp - flags_letter];
    9061    bb_show_usage();
    91     return 0;
    9262}
    9363
    94 static int decode_arg(char *arg)
     64static int decode_arg(const char *arg, struct globals *gp)
    9565{
    9666    unsigned long *fl;
    9767    char opt = *arg++;
    9868
     69    fl = &gp->af;
    9970    if (opt == '-') {
    100         flags |= OPT_REM;
    101         fl = &rf;
     71        gp->flags |= OPT_REM;
     72        fl = &gp->rf;
    10273    } else if (opt == '+') {
    103         flags |= OPT_ADD;
    104         fl = &af;
     74        gp->flags |= OPT_ADD;
    10575    } else if (opt == '=') {
    106         flags |= OPT_SET;
    107         fl = &sf;
     76        gp->flags |= OPT_SET;
    10877    } else
    109         return EOF;
     78        return 0;
    11079
    111     for (; *arg ; ++arg)
    112         (*fl) |= get_flag(*arg);
     80    while (*arg)
     81        *fl |= get_flag(*arg++);
    11382
    11483    return 1;
    11584}
    11685
    117 static int chattr_dir_proc(const char *, struct dirent *, void *);
     86static void change_attributes(const char *name, struct globals *gp);
    11887
    119 static void change_attributes(const char * name)
     88static int chattr_dir_proc(const char *dir_name, struct dirent *de, void *gp)
     89{
     90    char *path = concat_subpath_file(dir_name, de->d_name);
     91    /* path is NULL if de->d_name is "." or "..", else... */
     92    if (path) {
     93        change_attributes(path, gp);
     94        free(path);
     95    }
     96    return 0;
     97}
     98
     99static void change_attributes(const char *name, struct globals *gp)
    120100{
    121101    unsigned long fsflags;
    122     STRUCT_STAT st;
     102    struct stat st;
    123103
    124     if (LSTAT(name, &st) == -1) {
    125         bb_error_msg("stat %s failed", name);
     104    if (lstat(name, &st) != 0) {
     105        bb_perror_msg("stat %s", name);
    126106        return;
    127107    }
    128     if (S_ISLNK(st.st_mode) && recursive)
     108    if (S_ISLNK(st.st_mode) && gp->recursive)
    129109        return;
    130110
     
    136116        return;
    137117
    138     if (flags & OPT_SET_VER)
    139         if (fsetversion(name, version) == -1)
    140             bb_error_msg("setting version on %s", name);
     118    if (gp->flags & OPT_SET_VER)
     119        if (fsetversion(name, gp->version) != 0)
     120            bb_perror_msg("setting version on %s", name);
    141121
    142     if (flags & OPT_SET) {
    143         fsflags = sf;
     122    if (gp->flags & OPT_SET) {
     123        fsflags = gp->af;
    144124    } else {
    145         if (fgetflags(name, &fsflags) == -1) {
    146             bb_error_msg("reading flags on %s", name);
     125        if (fgetflags(name, &fsflags) != 0) {
     126            bb_perror_msg("reading flags on %s", name);
    147127            goto skip_setflags;
    148128        }
    149         if (flags & OPT_REM)
    150             fsflags &= ~rf;
    151         if (flags & OPT_ADD)
    152             fsflags |= af;
     129        /*if (gp->flags & OPT_REM) - not needed, rf is zero otherwise */
     130            fsflags &= ~gp->rf;
     131        /*if (gp->flags & OPT_ADD) - not needed, af is zero otherwise */
     132            fsflags |= gp->af;
     133        /* What is this? And why it's not done for SET case? */
    153134        if (!S_ISDIR(st.st_mode))
    154135            fsflags &= ~EXT2_DIRSYNC_FL;
    155136    }
    156     if (fsetflags(name, fsflags) == -1)
    157         bb_error_msg("setting flags on %s", name);
     137    if (fsetflags(name, fsflags) != 0)
     138        bb_perror_msg("setting flags on %s", name);
    158139
    159 skip_setflags:
    160     if (S_ISDIR(st.st_mode) && recursive)
    161         iterate_on_dir(name, chattr_dir_proc, NULL);
     140 skip_setflags:
     141    if (gp->recursive && S_ISDIR(st.st_mode))
     142        iterate_on_dir(name, chattr_dir_proc, gp);
    162143}
    163144
    164 static int chattr_dir_proc(const char *dir_name, struct dirent *de,
    165                void *private EXT2FS_ATTR((unused)))
    166 {
    167     /*if (strcmp(de->d_name, ".") && strcmp(de->d_name, "..")) {*/
    168     if (de->d_name[0] == '.' && (de->d_name[1] == '\0' || \
    169        (de->d_name[1] == '.' && de->d_name[2] == '\0'))) {
    170         char *path = concat_subpath_file(dir_name, de->d_name);
    171         if (path) {
    172             change_attributes(path);
    173             free(path);
    174         }
    175     }
    176     return 0;
    177 }
    178 
     145int chattr_main(int argc, char **argv);
    179146int chattr_main(int argc, char **argv)
    180147{
    181     int i;
     148    struct globals g;
    182149    char *arg;
    183150
     151    memset(&g, 0, sizeof(g));
     152
    184153    /* parse the args */
    185     for (i = 1; i < argc; ++i) {
    186         arg = argv[i];
    187 
     154    while ((arg = *++argv)) {
    188155        /* take care of -R and -v <version> */
    189         if (arg[0] == '-') {
    190             if (arg[1] == 'R' && arg[2] == '\0') {
    191                 recursive = 1;
    192                 continue;
    193             } else if (arg[1] == 'v' && arg[2] == '\0') {
    194                 char *tmp;
    195                 ++i;
    196                 if (i >= argc)
    197                     bb_show_usage();
    198                 version = strtol(argv[i], &tmp, 0);
    199                 if (*tmp)
    200                     bb_error_msg_and_die("bad version '%s'", arg);
    201                 flags |= OPT_SET_VER;
     156        if (arg[0] == '-'
     157         && (arg[1] == 'R' || arg[1] == 'v')
     158         && !arg[2]
     159        ) {
     160            if (arg[1] == 'R') {
     161                g.recursive = 1;
    202162                continue;
    203163            }
     164            /* arg[1] == 'v' */
     165            if (!*++argv)
     166                bb_show_usage();
     167            g.version = xatoul(*argv);
     168            g.flags |= OPT_SET_VER;
     169            continue;
    204170        }
    205171
    206         if (decode_arg(arg) == EOF)
     172        if (!decode_arg(arg, &g))
    207173            break;
    208174    }
    209175
    210176    /* run sanity checks on all the arguments given us */
    211     if (i >= argc)
     177    if (!*argv)
    212178        bb_show_usage();
    213     if ((flags & OPT_SET) && ((flags & OPT_ADD) || (flags & OPT_REM)))
     179    if ((g.flags & OPT_SET) && (g.flags & (OPT_ADD|OPT_REM)))
    214180        bb_error_msg_and_die("= is incompatible with - and +");
    215     if ((rf & af) != 0)
    216         bb_error_msg_and_die("Can't set and unset a flag");
    217     if (!flags)
    218         bb_error_msg_and_die("Must use '-v', =, - or +");
     181    if (g.rf & g.af)
     182        bb_error_msg_and_die("can't set and unset a flag");
     183    if (!g.flags)
     184        bb_error_msg_and_die("must use '-v', =, - or +");
    219185
    220186    /* now run chattr on all the files passed to us */
    221     while (i < argc)
    222         change_attributes(argv[i++]);
     187    do change_attributes(*argv, &g); while (*++argv);
    223188
    224189    return EXIT_SUCCESS;
  • branches/stable/mindi-busybox/e2fsprogs/fsck.c

    r821 r1770  
     1/* vi: set sw=4 ts=4: */
    12/*
    2  * pfsck --- A generic, parallelizing front-end for the fsck program.
     3 * fsck --- A generic, parallelizing front-end for the fsck program.
    34 * It will automatically try to run fsck programs in parallel if the
    45 * devices are on separate spindles.  It is based on the same ideas as
     
    2627 */
    2728
    28 #include <sys/types.h>
    29 #include <sys/wait.h>
    30 #include <sys/stat.h>
    31 #include <limits.h>
    32 #include <stdio.h>
    33 #include <ctype.h>
    34 #include <string.h>
    35 #include <time.h>
    36 #include <stdlib.h>
    37 #include <errno.h>
    38 #include <paths.h>
    39 #include <unistd.h>
    40 #include <errno.h>
    41 #include <signal.h>
    42 
    43 #include "fsck.h"
    44 #include "blkid/blkid.h"
    45 
    46 #include "e2fsbb.h"
    47 
    48 #include "busybox.h"
    49 
    50 #ifndef _PATH_MNTTAB
    51 #define _PATH_MNTTAB    "/etc/fstab"
    52 #endif
     29/* All filesystem specific hooks have been removed.
     30 * If filesystem cannot be determined, we will execute
     31 * "fsck.auto". Currently this also happens if you specify
     32 * UUID=xxx or LABEL=xxx as an object to check.
     33 * Detection code for that is also probably has to be in fsck.auto.
     34 *
     35 * In other words, this is _really_ is just a driver program which
     36 * spawns actual fsck.something for each filesystem to check.
     37 * It doesn't guess filesystem types from on-disk format.
     38 */
     39
     40#include "libbb.h"
     41
     42#define EXIT_OK          0
     43#define EXIT_NONDESTRUCT 1
     44#define EXIT_DESTRUCT    2
     45#define EXIT_UNCORRECTED 4
     46#define EXIT_ERROR       8
     47#define EXIT_USAGE       16
     48#define FSCK_CANCELED    32     /* Aborted with a signal or ^C */
    5349
    5450/*
    55  * fsck.h
    56  */
    57 
    58 #ifndef DEFAULT_FSTYPE
    59 #define DEFAULT_FSTYPE  "ext2"
    60 #endif
    61 
    62 #define MAX_DEVICES 32
    63 #define MAX_ARGS 32
    64 
    65 /*
    66  * Internal structure for mount tabel entries.
     51 * Internal structure for mount table entries.
    6752 */
    6853
    6954struct fs_info {
    70     char  *device;
    71     char  *mountpt;
    72     char  *type;
    73     char  *opts;
    74     int   freq;
    75     int   passno;
    76     int   flags;
    7755    struct fs_info *next;
     56    char    *device;
     57    char    *mountpt;
     58    char    *type;
     59    char    *opts;
     60    int freq;
     61    int passno;
     62    int flags;
    7863};
    7964
    8065#define FLAG_DONE 1
    8166#define FLAG_PROGRESS 2
    82 
    8367/*
    8468 * Structure to allow exit codes to be stored
    8569 */
    8670struct fsck_instance {
     71    struct fsck_instance *next;
    8772    int pid;
    8873    int flags;
    8974    int exit_status;
    9075    time_t  start_time;
    91     char *  prog;
    92     char *  type;
    93     char *  device;
    94     char *  base_device;
    95     struct fsck_instance *next;
     76    char    *prog;
     77    char    *type;
     78    char    *device;
     79    char    *base_device; /* /dev/hda for /dev/hdaN etc */
    9680};
    9781
     82static const char ignored_types[] ALIGN1 =
     83    "ignore\0"
     84    "iso9660\0"
     85    "nfs\0"
     86    "proc\0"
     87    "sw\0"
     88    "swap\0"
     89    "tmpfs\0"
     90    "devpts\0";
     91
     92#if 0
     93static const char really_wanted[] ALIGN1 =
     94    "minix\0"
     95    "ext2\0"
     96    "ext3\0"
     97    "jfs\0"
     98    "reiserfs\0"
     99    "xiafs\0"
     100    "xfs\0";
     101#endif
     102
     103#define BASE_MD "/dev/md"
     104
     105static char **devices;
     106static char **args;
     107static int num_devices;
     108static int num_args;
     109static int verbose;
     110
     111#define FS_TYPE_FLAG_NORMAL 0
     112#define FS_TYPE_FLAG_OPT    1
     113#define FS_TYPE_FLAG_NEGOPT 2
     114static char **fs_type_list;
     115static uint8_t *fs_type_flag;
     116static smallint fs_type_negated;
     117
     118static volatile smallint cancel_requested;
     119static smallint doall;
     120static smallint noexecute;
     121static smallint serialize;
     122static smallint skip_root;
     123/* static smallint like_mount; */
     124static smallint notitle;
     125static smallint parallel_root;
     126static smallint force_all_parallel;
     127
     128/* "progress indicator" code is somewhat buggy and ext[23] specific.
     129 * We should be filesystem agnostic. IOW: there should be a well-defined
     130 * API for fsck.something, NOT ad-hoc hacks in generic fsck. */
     131#define DO_PROGRESS_INDICATOR 0
     132#if DO_PROGRESS_INDICATOR
     133static smallint progress;
     134static int progress_fd;
     135#endif
     136
     137static int num_running;
     138static int max_running;
     139static char *fstype;
     140static struct fs_info *filesys_info;
     141static struct fs_info *filesys_last;
     142static struct fsck_instance *instance_list;
     143
    98144/*
    99  * base_device.c
    100  *
    101145 * Return the "base device" given a particular device; this is used to
    102146 * assure that we only fsck one partition on a particular drive at any
    103147 * one time.  Otherwise, the disk heads will be seeking all over the
    104  * place.  If the base device can not be determined, return NULL.
     148 * place.  If the base device cannot be determined, return NULL.
    105149 *
    106150 * The base_device() function returns an allocated string which must
    107151 * be freed.
    108  *
    109  */
    110 
    111 
    112 #ifdef CONFIG_FEATURE_DEVFS
     152 */
     153#if ENABLE_FEATURE_DEVFS
    113154/*
    114155 * Required for the uber-silly devfs /dev/ide/host1/bus2/target3/lun3
    115156 * pathames.
    116157 */
    117 static const char * const devfs_hier[] = {
    118     "host", "bus", "target", "lun", 0
     158static const char *const devfs_hier[] = {
     159    "host", "bus", "target", "lun", NULL
    119160};
    120161#endif
     
    123164{
    124165    char *str, *cp;
    125 #ifdef CONFIG_FEATURE_DEVFS
    126     const char * const *hier;
     166#if ENABLE_FEATURE_DEVFS
     167    const char *const *hier;
    127168    const char *disk;
    128169    int len;
    129170#endif
    130 
    131     cp = str = bb_xstrdup(device);
     171    cp = str = xstrdup(device);
    132172
    133173    /* Skip over /dev/; if it's not present, give up. */
     
    135175        goto errout;
    136176    cp += 5;
    137 
    138 #if 0   /* this is for old stuff no one uses anymore ? */
    139     /* Skip over /dev/dsk/... */
    140     if (strncmp(cp, "dsk/", 4) == 0)
    141         cp += 4;
    142 #endif
    143177
    144178    /*
     
    147181     */
    148182    if (cp[0] == 'm' && cp[1] == 'd') {
    149         *(cp+2) = 0;
     183        cp[2] = 0;
    150184        return str;
    151185    }
     
    154188    if (strncmp(cp, "rd/", 3) == 0) {
    155189        cp += 3;
    156         if (cp[0] != 'c' || cp[2] != 'd' ||
    157             !isdigit(cp[1]) || !isdigit(cp[3]))
     190        if (cp[0] != 'c' || !isdigit(cp[1])
     191         || cp[2] != 'd' || !isdigit(cp[3]))
    158192            goto errout;
    159         *(cp+4) = 0;
     193        cp[4] = 0;
    160194        return str;
    161195    }
    162196
    163197    /* Now let's handle /dev/hd* and /dev/sd* devices.... */
    164     if ((cp[0] == 'h' || cp[0] == 's') && (cp[1] == 'd')) {
     198    if ((cp[0] == 'h' || cp[0] == 's') && cp[1] == 'd') {
    165199        cp += 2;
    166200        /* If there's a single number after /dev/hd, skip it */
     
    170204        if (!isalpha(*cp))
    171205            goto errout;
    172         *(cp + 1) = 0;
     206        cp[1] = 0;
    173207        return str;
    174208    }
    175209
    176 #ifdef CONFIG_FEATURE_DEVFS
     210#if ENABLE_FEATURE_DEVFS
    177211    /* Now let's handle devfs (ugh) names */
    178212    len = 0;
     
    201235            cp++;
    202236        }
    203         *(cp - 1) = 0;
     237        cp[-1] = 0;
    204238        return str;
    205239    }
     
    225259    }
    226260#endif
    227 
    228 errout:
     261 errout:
    229262    free(str);
    230263    return NULL;
    231264}
    232265
    233 
    234 static const char * const ignored_types[] = {
    235     "ignore",
    236     "iso9660",
    237     "nfs",
    238     "proc",
    239     "sw",
    240     "swap",
    241     "tmpfs",
    242     "devpts",
    243     NULL
    244 };
    245 
    246 static const char * const really_wanted[] = {
    247     "minix",
    248     "ext2",
    249     "ext3",
    250     "jfs",
    251     "reiserfs",
    252     "xiafs",
    253     "xfs",
    254     NULL
    255 };
    256 
    257 #define BASE_MD "/dev/md"
    258 
    259 /*
    260  * Global variables for options
    261  */
    262 static char *devices[MAX_DEVICES];
    263 static char *args[MAX_ARGS];
    264 static int num_devices, num_args;
    265 
    266 static int verbose;
    267 static int doall;
    268 static int noexecute;
    269 static int serialize;
    270 static int skip_root;
    271 static int like_mount;
    272 static int notitle;
    273 static int parallel_root;
    274 static int progress;
    275 static int progress_fd;
    276 static int force_all_parallel;
    277 static int num_running;
    278 static int max_running;
    279 static volatile int cancel_requested;
    280 static int kill_sent;
    281 static char *fstype;
    282 static struct fs_info *filesys_info, *filesys_last;
    283 static struct fsck_instance *instance_list;
    284 static char *fsck_path;
    285 static blkid_cache cache;
    286 
    287 static char *string_copy(const char *s)
    288 {
    289     char    *ret;
    290 
    291     if (!s)
    292         return 0;
    293     ret = strdup(s);
    294     return ret;
    295 }
    296 
    297 static int string_to_int(const char *s)
    298 {
    299     long l;
    300     char *p;
    301 
    302     l = strtol(s, &p, 0);
    303     if (*p || l == LONG_MIN || l == LONG_MAX || l < 0 || l > INT_MAX)
    304         return -1;
     266static void free_instance(struct fsck_instance *p)
     267{
     268    free(p->prog);
     269    free(p->device);
     270    free(p->base_device);
     271    free(p);
     272}
     273
     274static struct fs_info *create_fs_device(const char *device, const char *mntpnt,
     275                    const char *type, const char *opts,
     276                    int freq, int passno)
     277{
     278    struct fs_info *fs;
     279
     280    fs = xzalloc(sizeof(*fs));
     281    fs->device = xstrdup(device);
     282    fs->mountpt = xstrdup(mntpnt);
     283    fs->type = xstrdup(type);
     284    fs->opts = xstrdup(opts ? opts : "");
     285    fs->freq = freq;
     286    fs->passno = passno;
     287    /*fs->flags = 0; */
     288    /*fs->next = NULL; */
     289
     290    if (!filesys_info)
     291        filesys_info = fs;
    305292    else
    306         return (int) l;
    307 }
    308 
    309 static char *skip_over_blank(char *cp)
    310 {
    311     while (*cp && isspace(*cp))
    312         cp++;
    313     return cp;
    314 }
    315 
    316 static char *skip_over_word(char *cp)
    317 {
    318     while (*cp && !isspace(*cp))
    319         cp++;
    320     return cp;
     293        filesys_last->next = fs;
     294    filesys_last = fs;
     295
     296    return fs;
    321297}
    322298
    323299static void strip_line(char *line)
    324300{
    325     char    *p;
     301    char *p = line + strlen(line) - 1;
    326302
    327303    while (*line) {
    328         p = line + strlen(line) - 1;
    329         if ((*p == '\n') || (*p == '\r'))
    330             *p = 0;
    331         else
     304        if (*p != '\n' && *p != '\r')
    332305            break;
     306        *p-- = '\0';
    333307    }
    334308}
     
    339313
    340314    word = *buf;
    341     if (*word == 0)
    342         return 0;
    343 
    344     word = skip_over_blank(word);
    345     next = skip_over_word(word);
     315    if (*word == '\0')
     316        return NULL;
     317
     318    word = skip_whitespace(word);
     319    next = skip_non_whitespace(word);
    346320    if (*next)
    347         *next++ = 0;
     321        *next++ = '\0';
    348322    *buf = next;
    349323    return word;
     
    352326static void parse_escape(char *word)
    353327{
    354     char    *q, c;
     328    char *q, c;
    355329    const char *p;
    356330
     
    366340        }
    367341    }
    368     *q = 0;
    369 }
    370 
    371 static void free_instance(struct fsck_instance *i)
    372 {
    373     if (i->prog)
    374         free(i->prog);
    375     if (i->device)
    376         free(i->device);
    377     if (i->base_device)
    378         free(i->base_device);
    379     free(i);
    380     return;
    381 }
    382 
    383 static struct fs_info *create_fs_device(const char *device, const char *mntpnt,
    384                     const char *type, const char *opts,
    385                     int freq, int passno)
    386 {
    387     struct fs_info *fs;
    388 
    389     if (!(fs = malloc(sizeof(struct fs_info))))
    390         return NULL;
    391 
    392     fs->device = string_copy(device);
    393     fs->mountpt = string_copy(mntpnt);
    394     fs->type = string_copy(type);
    395     fs->opts = string_copy(opts ? opts : "");
    396     fs->freq = freq;
    397     fs->passno = passno;
    398     fs->flags = 0;
    399     fs->next = NULL;
    400 
    401     if (!filesys_info)
    402         filesys_info = fs;
    403     else
    404         filesys_last->next = fs;
    405     filesys_last = fs;
    406 
    407     return fs;
    408 }
    409 
    410 
     342    *q = '\0';
     343}
    411344
    412345static int parse_fstab_line(char *line, struct fs_info **ret_fs)
    413346{
    414     char    *dev, *device, *mntpnt, *type, *opts, *freq, *passno, *cp;
     347    char *device, *mntpnt, *type, *opts, *freq, *passno, *cp;
    415348    struct fs_info *fs;
    416349
    417350    *ret_fs = 0;
    418351    strip_line(line);
    419     if ((cp = strchr(line, '#')))
    420         *cp = 0;        /* Ignore everything after the comment char */
     352    cp = strchr(line, '#');
     353    if (cp)
     354        *cp = '\0'; /* Ignore everything after the comment char */
    421355    cp = line;
    422356
    423357    device = parse_word(&cp);
     358    if (!device) return 0; /* Allow blank lines */
    424359    mntpnt = parse_word(&cp);
    425360    type = parse_word(&cp);
     
    427362    freq = parse_word(&cp);
    428363    passno = parse_word(&cp);
    429 
    430     if (!device)
    431         return 0;       /* Allow blank lines */
    432364
    433365    if (!mntpnt || !type)
     
    441373    parse_escape(passno);
    442374
    443     dev = blkid_get_devname(cache, device, NULL);
    444     if (dev)
    445         device = dev;
    446 
    447375    if (strchr(type, ','))
    448         type = 0;
     376        type = NULL;
    449377
    450378    fs = create_fs_device(device, mntpnt, type ? type : "auto", opts,
    451                   freq ? atoi(freq) : -1,
    452                   passno ? atoi(passno) : -1);
    453     if (dev)
    454         free(dev);
    455 
    456     if (!fs)
    457         return -1;
     379                freq ? atoi(freq) : -1,
     380                passno ? atoi(passno) : -1);
    458381    *ret_fs = fs;
    459382    return 0;
    460383}
    461384
    462 static void interpret_type(struct fs_info *fs)
    463 {
    464     char    *t;
    465 
    466     if (strcmp(fs->type, "auto") != 0)
     385/* Load the filesystem database from /etc/fstab */
     386static void load_fs_info(const char *filename)
     387{
     388    FILE *f;
     389    int lineno = 0;
     390    int old_fstab = 1;
     391    struct fs_info *fs;
     392
     393    f = fopen_or_warn(filename, "r");
     394    if (f == NULL) {
    467395        return;
    468     t = blkid_get_tag_value(cache, "TYPE", fs->device);
    469     if (t) {
    470         free(fs->type);
    471         fs->type = t;
    472     }
    473 }
    474 
    475 /*
    476  * Load the filesystem database from /etc/fstab
    477  */
    478 static void load_fs_info(const char *filename)
    479 {
    480     FILE    *f;
    481     char    buf[1024];
    482     int     lineno = 0;
    483     int     old_fstab = 1;
    484     struct fs_info *fs;
    485 
    486     if ((f = fopen(filename, "r")) == NULL) {
    487         bb_perror_msg("WARNING: couldn't open %s", filename);
    488         return;
    489     }
    490     while (!feof(f)) {
     396    }
     397    while (1) {
     398        int r;
     399        char *buf = xmalloc_getline(f);
     400        if (!buf) break;
     401        r = parse_fstab_line(buf, &fs);
     402        free(buf);
    491403        lineno++;
    492         if (!fgets(buf, sizeof(buf), f))
    493             break;
    494         buf[sizeof(buf)-1] = 0;
    495         if (parse_fstab_line(buf, &fs) < 0) {
     404        if (r < 0) {
    496405            bb_error_msg("WARNING: bad format "
    497                 "on line %d of %s\n", lineno, filename);
     406                "on line %d of %s", lineno, filename);
    498407            continue;
    499408        }
     
    505414            old_fstab = 0;
    506415    }
    507 
    508416    fclose(f);
    509417
    510418    if (old_fstab) {
    511         fputs("\007\007\007"
    512         "WARNING: Your /etc/fstab does not contain the fsck passno\n"
    513         "       field.  I will kludge around things for you, but you\n"
    514         "       should fix your /etc/fstab file as soon as you can.\n\n", stderr);
    515 
     419        fputs("\007"
     420"WARNING: Your /etc/fstab does not contain the fsck passno field.\n"
     421"I will kludge around things for you, but you should fix\n"
     422"your /etc/fstab file as soon as you can.\n\n", stderr);
    516423        for (fs = filesys_info; fs; fs = fs->next) {
    517424            fs->passno = 1;
     
    525432    struct fs_info *fs;
    526433
    527     /* No filesys name given. */
    528     if (filesys == NULL)
    529         return NULL;
    530 
    531434    for (fs = filesys_info; fs; fs = fs->next) {
    532         if (!strcmp(filesys, fs->device) ||
    533             (fs->mountpt && !strcmp(filesys, fs->mountpt)))
     435        if (strcmp(filesys, fs->device) == 0
     436         || (fs->mountpt && strcmp(filesys, fs->mountpt) == 0)
     437        )
    534438            break;
    535439    }
     
    538442}
    539443
    540 /* Find fsck program for a given fs type. */
    541 static char *find_fsck(char *type)
    542 {
    543   char *s;
    544   const char *tpl;
    545   char *p = string_copy(fsck_path);
    546   struct stat st;
    547 
    548   /* Are we looking for a program or just a type? */
    549   tpl = (strncmp(type, "fsck.", 5) ? "%s/fsck.%s" : "%s/%s");
    550 
    551   for(s = strtok(p, ":"); s; s = strtok(NULL, ":")) {
    552     s = bb_xasprintf(tpl, s, type);
    553     if (stat(s, &st) == 0) break;
    554     free(s);
    555   }
    556   free(p);
    557   return(s);
    558 }
    559 
     444#if DO_PROGRESS_INDICATOR
    560445static int progress_active(void)
    561446{
     
    570455    return 0;
    571456}
    572 
    573 /*
    574  * Execute a particular fsck program, and link it into the list of
    575  * child processes we are waiting for.
    576  */
    577 static int execute(const char *type, const char *device, const char *mntpt,
    578            int interactive)
    579 {
    580     char *s, *argv[80];
    581     char *prog;
    582     int  argc, i;
    583     struct fsck_instance *inst, *p;
    584     pid_t   pid;
    585 
    586     inst = malloc(sizeof(struct fsck_instance));
    587     if (!inst)
    588         return ENOMEM;
    589     memset(inst, 0, sizeof(struct fsck_instance));
    590 
    591     prog = bb_xasprintf("fsck.%s", type);
    592     argv[0] = prog;
    593     argc = 1;
    594 
    595     for (i=0; i <num_args; i++)
    596         argv[argc++] = string_copy(args[i]);
    597 
    598     if (progress && !progress_active()) {
    599         if ((strcmp(type, "ext2") == 0) ||
    600             (strcmp(type, "ext3") == 0)) {
    601             char tmp[80];
    602             snprintf(tmp, 80, "-C%d", progress_fd);
    603             argv[argc++] = string_copy(tmp);
    604             inst->flags |= FLAG_PROGRESS;
    605         }
    606     }
    607 
    608     argv[argc++] = string_copy(device);
    609     argv[argc] = 0;
    610 
    611     s = find_fsck(prog);
    612     if (s == NULL) {
    613         bb_error_msg("%s: not found", prog);
    614         return ENOENT;
    615     }
    616 
    617     if (verbose || noexecute) {
    618         printf("[%s (%d) -- %s] ", s, num_running,
    619                mntpt ? mntpt : device);
    620         for (i=0; i < argc; i++)
    621             printf("%s ", argv[i]);
    622         printf("\n");
    623     }
    624 
    625     /* Fork and execute the correct program. */
    626     if (noexecute)
    627         pid = -1;
    628     else if ((pid = fork()) < 0) {
    629         perror("fork");
    630         return errno;
    631     } else if (pid == 0) {
    632         if (!interactive)
    633             close(0);
    634         (void) execv(s, argv);
    635         bb_perror_msg_and_die("%s", argv[0]);
    636     }
    637 
    638     for (i = 1; i < argc; i++)
    639         free(argv[i]);
    640 
    641     free(s);
    642     inst->pid = pid;
    643     inst->prog = prog;
    644     inst->type = string_copy(type);
    645     inst->device = string_copy(device);
    646     inst->base_device = base_device(device);
    647     inst->start_time = time(0);
    648     inst->next = NULL;
    649 
    650     /*
    651      * Find the end of the list, so we add the instance on at the end.
    652      */
    653     for (p = instance_list; p && p->next; p = p->next);
    654 
    655     if (p)
    656         p->next = inst;
    657     else
    658         instance_list = inst;
    659 
    660     return 0;
    661 }
     457#endif
     458
    662459
    663460/*
    664461 * Send a signal to all outstanding fsck child processes
    665462 */
    666 static int kill_all(int signum)
    667 {
     463static void kill_all_if_cancel_requested(void)
     464{
     465    static smallint kill_sent;
     466
    668467    struct fsck_instance *inst;
    669     int     n = 0;
     468
     469    if (!cancel_requested || kill_sent)
     470        return;
    670471
    671472    for (inst = instance_list; inst; inst = inst->next) {
    672473        if (inst->flags & FLAG_DONE)
    673474            continue;
    674         kill(inst->pid, signum);
    675         n++;
    676     }
    677     return n;
     475        kill(inst->pid, SIGTERM);
     476    }
     477    kill_sent = 1;
    678478}
    679479
     
    684484static struct fsck_instance *wait_one(int flags)
    685485{
    686     int     status;
    687     int     sig;
    688     struct fsck_instance *inst, *inst2, *prev;
    689     pid_t   pid;
     486    int status;
     487    int sig;
     488    struct fsck_instance *inst, *prev;
     489    pid_t pid;
    690490
    691491    if (!instance_list)
     
    694494    if (noexecute) {
    695495        inst = instance_list;
    696         prev = 0;
     496        prev = NULL;
    697497#ifdef RANDOM_DEBUG
    698498        while (inst->next && (random() & 1)) {
     
    705505    }
    706506
    707     /*
    708      * gcc -Wall fails saving throw against stupidity
    709      * (inst and prev are thought to be uninitialized variables)
    710      */
    711     inst = prev = NULL;
    712 
     507    inst = prev = NULL; /* for gcc */
    713508    do {
    714509        pid = waitpid(-1, &status, flags);
    715         if (cancel_requested && !kill_sent) {
    716             kill_all(SIGTERM);
    717             kill_sent++;
    718         }
    719         if ((pid == 0) && (flags & WNOHANG))
     510        kill_all_if_cancel_requested();
     511        if (pid == 0 && (flags & WNOHANG))
    720512            return NULL;
    721513        if (pid < 0) {
    722             if ((errno == EINTR) || (errno == EAGAIN))
     514            if (errno == EINTR || errno == EAGAIN)
    723515                continue;
    724516            if (errno == ECHILD) {
    725                 bb_error_msg("wait: No more child process?!?");
     517                bb_error_msg("wait: no more child process?!?");
    726518                return NULL;
    727519            }
    728             perror("wait");
     520            bb_perror_msg("wait");
    729521            continue;
    730522        }
    731         for (prev = 0, inst = instance_list;
    732              inst;
    733              prev = inst, inst = inst->next) {
     523        prev = NULL;
     524        inst = instance_list;
     525        while (inst) {
    734526            if (inst->pid == pid)
    735527                break;
     528            prev = inst;
     529            inst = inst->next;
    736530        }
    737531    } while (!inst);
     
    741535    else if (WIFSIGNALED(status)) {
    742536        sig = WTERMSIG(status);
    743         if (sig == SIGINT) {
    744             status = EXIT_UNCORRECTED;
    745         } else {
    746             printf("Warning... %s for device %s exited "
    747                    "with signal %d.\n",
    748                    inst->prog, inst->device, sig);
     537        status = EXIT_UNCORRECTED;
     538        if (sig != SIGINT) {
     539            printf("Warning... %s %s exited "
     540                "with signal %d\n",
     541                inst->prog, inst->device, sig);
    749542            status = EXIT_ERROR;
    750543        }
    751544    } else {
    752         printf("%s %s: status is %x, should never happen.\n",
    753                inst->prog, inst->device, status);
     545        printf("%s %s: status is %x, should never happen\n",
     546            inst->prog, inst->device, status);
    754547        status = EXIT_ERROR;
    755548    }
    756549    inst->exit_status = status;
    757     if (progress && (inst->flags & FLAG_PROGRESS) &&
    758         !progress_active()) {
     550
     551#if DO_PROGRESS_INDICATOR
     552    if (progress && (inst->flags & FLAG_PROGRESS) && !progress_active()) {
     553        struct fsck_instance *inst2;
    759554        for (inst2 = instance_list; inst2; inst2 = inst2->next) {
    760555            if (inst2->flags & FLAG_DONE)
    761556                continue;
    762             if (strcmp(inst2->type, "ext2") &&
    763                 strcmp(inst2->type, "ext3"))
     557            if (strcmp(inst2->type, "ext2") != 0
     558             && strcmp(inst2->type, "ext3") != 0
     559            ) {
    764560                continue;
    765             /*
     561            }
     562            /* ext[23], we will send USR1
     563             * (request to start displaying progress bar)
     564             *
    766565             * If we've just started the fsck, wait a tiny
    767566             * bit before sending the kill, to give it
    768567             * time to set up the signal handler
    769568             */
    770             if (inst2->start_time < time(0)+2) {
    771                 if (fork() == 0) {
    772                     sleep(1);
    773                     kill(inst2->pid, SIGUSR1);
    774                     exit(0);
    775                 }
    776             } else
    777                 kill(inst2->pid, SIGUSR1);
     569            if (inst2->start_time >= time(NULL) - 1)
     570                sleep(1);
     571            kill(inst2->pid, SIGUSR1);
    778572            inst2->flags |= FLAG_PROGRESS;
    779573            break;
    780574        }
    781575    }
    782 ret_inst:
     576#endif
     577
     578 ret_inst:
    783579    if (prev)
    784580        prev->next = inst->next;
     
    801597{
    802598    struct fsck_instance *inst;
    803     int     global_status = 0;
    804     int     wait_flags = 0;
     599    int global_status = 0;
     600    int wait_flags = 0;
    805601
    806602    while ((inst = wait_one(wait_flags))) {
     
    818614
    819615/*
     616 * Execute a particular fsck program, and link it into the list of
     617 * child processes we are waiting for.
     618 */
     619static void execute(const char *type, const char *device, const char *mntpt,
     620        int interactive)
     621{
     622    char *argv[num_args + 4]; /* see count below: */
     623    int argc;
     624    int i;
     625    struct fsck_instance *inst;
     626    pid_t pid;
     627
     628    inst = xzalloc(sizeof(*inst));
     629
     630    argv[0] = xasprintf("fsck.%s", type); /* 1 */
     631    for (i = 0; i < num_args; i++)
     632        argv[i+1] = args[i]; /* num_args */
     633    argc = num_args + 1;
     634
     635#if DO_PROGRESS_INDICATOR
     636    if (progress && !progress_active()) {
     637        if (strcmp(type, "ext2") == 0
     638         || strcmp(type, "ext3") == 0
     639        ) {
     640            argv[argc++] = xasprintf("-C%d", progress_fd); /* 1 */
     641            inst->flags |= FLAG_PROGRESS;
     642        }
     643    }
     644#endif
     645
     646    argv[argc++] = xstrdup(device); /* 1 */
     647    argv[argc] = NULL; /* 1 */
     648
     649    if (verbose || noexecute) {
     650        printf("[%s (%d) -- %s]", argv[0], num_running,
     651                    mntpt ? mntpt : device);
     652        for (i = 0; i < argc; i++)
     653            printf(" %s", argv[i]);
     654        puts("");
     655    }
     656
     657    /* Fork and execute the correct program. */
     658    pid = -1;
     659    if (!noexecute) {
     660        pid = spawn(argv);
     661        if (pid < 0)
     662            bb_perror_msg("%s", argv[0]);
     663    }
     664
     665    for (i = num_args+1; i < argc; i++)
     666        free(argv[i]);
     667
     668    inst->pid = pid;
     669    inst->prog = argv[0];
     670    inst->type = xstrdup(type);
     671    inst->device = xstrdup(device);
     672    inst->base_device = base_device(device);
     673    inst->start_time = time(NULL);
     674
     675    /* Add to the list of running fsck's.
     676     * (was adding to the end, but adding to the front is simpler...) */
     677    inst->next = instance_list;
     678    instance_list = inst;
     679}
     680
     681/*
    820682 * Run the fsck program on a particular device
    821683 *
     
    825687 *
    826688 * If the type isn't specified by the user, then use either the type
    827  * specified in /etc/fstab, or DEFAULT_FSTYPE.
     689 * specified in /etc/fstab, or "auto".
    828690 */
    829691static void fsck_device(struct fs_info *fs, int interactive)
    830692{
    831693    const char *type;
    832     int retval;
    833 
    834     interpret_type(fs);
    835 
    836     if (strcmp(fs->type, "auto") != 0)
     694
     695    if (strcmp(fs->type, "auto") != 0) {
    837696        type = fs->type;
    838     else if (fstype && strncmp(fstype, "no", 2) &&
    839         strncmp(fstype, "opts=", 5) && strncmp(fstype, "loop", 4) &&
    840         !strchr(fstype, ','))
     697        if (verbose > 2)
     698            bb_info_msg("using filesystem type '%s' %s",
     699                    type, "from fstab");
     700    } else if (fstype
     701     && (fstype[0] != 'n' || fstype[1] != 'o') /* != "no" */
     702     && strncmp(fstype, "opts=", 5) != 0
     703     && strncmp(fstype, "loop", 4) != 0
     704     && !strchr(fstype, ',')
     705    ) {
    841706        type = fstype;
    842     else
    843         type = DEFAULT_FSTYPE;
     707        if (verbose > 2)
     708            bb_info_msg("using filesystem type '%s' %s",
     709                    type, "from -t");
     710    } else {
     711        type = "auto";
     712        if (verbose > 2)
     713            bb_info_msg("using filesystem type '%s' %s",
     714                    type, "(default)");
     715    }
    844716
    845717    num_running++;
    846     retval = execute(type, fs->device, fs->mountpt, interactive);
    847     if (retval) {
    848         bb_error_msg("Error %d while executing fsck.%s for %s",
    849                         retval, type, fs->device);
    850         num_running--;
    851     }
    852 }
    853 
    854 
    855 /*
    856  * Deal with the fsck -t argument.
    857  */
    858 struct fs_type_compile {
    859     char **list;
    860     int *type;
    861     int  negate;
    862 } fs_type_compiled;
    863 
    864 #define FS_TYPE_NORMAL  0
    865 #define FS_TYPE_OPT     1
    866 #define FS_TYPE_NEGOPT  2
    867 
    868 static const char fs_type_syntax_error[] =
    869 "Either all or none of the filesystem types passed to -t must be prefixed\n"
    870    "with 'no' or '!'.";
    871 
    872 static void compile_fs_type(char *fs_type, struct fs_type_compile *cmp)
    873 {
    874     char    *cp, *list, *s;
    875     int     num = 2;
    876     int     negate, first_negate = 1;
    877 
    878     if (fs_type) {
    879         for (cp=fs_type; *cp; cp++) {
    880             if (*cp == ',')
    881                 num++;
    882         }
    883     }
    884 
    885     cmp->list = xcalloc(num, sizeof(char *));
    886     cmp->type = xcalloc(num, sizeof(int));
    887     cmp->negate = 0;
    888 
    889     if (!fs_type)
    890         return;
    891 
    892     list = string_copy(fs_type);
    893     num = 0;
    894     s = strtok(list, ",");
    895     while(s) {
    896         negate = 0;
    897         if (strncmp(s, "no", 2) == 0) {
    898             s += 2;
    899             negate = 1;
    900         } else if (*s == '!') {
    901             s++;
    902             negate = 1;
    903         }
    904         if (strcmp(s, "loop") == 0)
    905             /* loop is really short-hand for opts=loop */
    906             goto loop_special_case;
    907         else if (strncmp(s, "opts=", 5) == 0) {
    908             s += 5;
    909         loop_special_case:
    910             cmp->type[num] = negate ? FS_TYPE_NEGOPT : FS_TYPE_OPT;
    911         } else {
    912             if (first_negate) {
    913                 cmp->negate = negate;
    914                 first_negate = 0;
    915             }
    916             if ((negate && !cmp->negate) ||
    917                 (!negate && cmp->negate)) {
    918                 bb_error_msg_and_die("%s", fs_type_syntax_error);
    919             }
    920         }
    921 #if 0
    922         printf("Adding %s to list (type %d).\n", s, cmp->type[num]);
    923 #endif
    924         cmp->list[num++] = string_copy(s);
    925         s = strtok(NULL, ",");
    926     }
    927     free(list);
    928 }
    929 
    930 /*
    931  * This function returns true if a particular option appears in a
    932  * comma-delimited options list
    933  */
    934 static int opt_in_list(char *opt, char *optlist)
    935 {
    936     char    *list, *s;
    937 
    938     if (!optlist)
    939         return 0;
    940     list = string_copy(optlist);
    941 
    942     s = strtok(list, ",");
    943     while(s) {
    944         if (strcmp(s, opt) == 0) {
    945             free(list);
    946             return 1;
    947         }
    948         s = strtok(NULL, ",");
    949     }
    950     free(list);
    951     return 0;
    952 }
    953 
    954 /* See if the filesystem matches the criteria given by the -t option */
    955 static int fs_match(struct fs_info *fs, struct fs_type_compile *cmp)
    956 {
    957     int n, ret = 0, checked_type = 0;
    958     char *cp;
    959 
    960     if (cmp->list == 0 || cmp->list[0] == 0)
    961         return 1;
    962 
    963     for (n=0; (cp = cmp->list[n]); n++) {
    964         switch (cmp->type[n]) {
    965         case FS_TYPE_NORMAL:
    966             checked_type++;
    967             if (strcmp(cp, fs->type) == 0) {
    968                 ret = 1;
    969             }
    970             break;
    971         case FS_TYPE_NEGOPT:
    972             if (opt_in_list(cp, fs->opts))
    973                 return 0;
    974             break;
    975         case FS_TYPE_OPT:
    976             if (!opt_in_list(cp, fs->opts))
    977                 return 0;
    978             break;
    979         }
    980     }
    981     if (checked_type == 0)
    982         return 1;
    983     return (cmp->negate ? !ret : ret);
    984 }
    985 
    986 /* Check if we should ignore this filesystem. */
    987 static int ignore(struct fs_info *fs)
    988 {
    989     int wanted;
    990     char *s;
    991 
    992     /*
    993      * If the pass number is 0, ignore it.
    994      */
    995     if (fs->passno == 0)
    996         return 1;
    997 
    998     interpret_type(fs);
    999 
    1000     /*
    1001      * If a specific fstype is specified, and it doesn't match,
    1002      * ignore it.
    1003      */
    1004     if (!fs_match(fs, &fs_type_compiled)) return 1;
    1005 
    1006     /* Are we ignoring this type? */
    1007     if(compare_string_array(ignored_types, fs->type) >= 0)
    1008         return 1;
    1009 
    1010     /* Do we really really want to check this fs? */
    1011     wanted = compare_string_array(really_wanted, fs->type) >= 0;
    1012 
    1013     /* See if the <fsck.fs> program is available. */
    1014     s = find_fsck(fs->type);
    1015     if (s == NULL) {
    1016         if (wanted)
    1017             bb_error_msg("cannot check %s: fsck.%s not found",
    1018                 fs->device, fs->type);
    1019         return 1;
    1020     }
    1021     free(s);
    1022 
    1023     /* We can and want to check this file system type. */
    1024     return 0;
     718    execute(type, fs->device, fs->mountpt, interactive);
    1025719}
    1026720
     
    1039733#ifdef BASE_MD
    1040734    /* Don't check a soft raid disk with any other disk */
    1041     if (instance_list &&
    1042         (!strncmp(instance_list->device, BASE_MD, sizeof(BASE_MD)-1) ||
    1043          !strncmp(device, BASE_MD, sizeof(BASE_MD)-1)))
     735    if (instance_list
     736     && (!strncmp(instance_list->device, BASE_MD, sizeof(BASE_MD)-1)
     737         || !strncmp(device, BASE_MD, sizeof(BASE_MD)-1))
     738    ) {
    1044739        return 1;
     740    }
    1045741#endif
    1046742
     
    1051747     */
    1052748    if (!base)
    1053         return (instance_list != 0);
     749        return (instance_list != NULL);
     750
    1054751    for (inst = instance_list; inst; inst = inst->next) {
    1055752        if (!inst->base_device || !strcmp(base, inst->base_device)) {
     
    1058755        }
    1059756    }
     757
    1060758    free(base);
    1061759    return 0;
    1062760}
    1063761
     762/*
     763 * This function returns true if a particular option appears in a
     764 * comma-delimited options list
     765 */
     766static int opt_in_list(char *opt, char *optlist)
     767{
     768    char *s;
     769    int len;
     770
     771    if (!optlist)
     772        return 0;
     773
     774    len = strlen(opt);
     775    s = optlist - 1;
     776    while (1) {
     777        s = strstr(s + 1, opt);
     778        if (!s)
     779            return 0;
     780        /* neither "opt.." nor "xxx,opt.."? */
     781        if (s != optlist && s[-1] != ',')
     782            continue;
     783        /* neither "..opt" nor "..opt,xxx"? */
     784        if (s[len] != '\0' && s[len] != ',')
     785            continue;
     786        return 1;
     787    }
     788}
     789
     790/* See if the filesystem matches the criteria given by the -t option */
     791static int fs_match(struct fs_info *fs)
     792{
     793    int n, ret, checked_type;
     794    char *cp;
     795
     796    if (!fs_type_list)
     797        return 1;
     798
     799    ret = 0;
     800    checked_type = 0;
     801    n = 0;
     802    while (1) {
     803        cp = fs_type_list[n];
     804        if (!cp)
     805            break;
     806        switch (fs_type_flag[n]) {
     807        case FS_TYPE_FLAG_NORMAL:
     808            checked_type++;
     809            if (strcmp(cp, fs->type) == 0)
     810                ret = 1;
     811            break;
     812        case FS_TYPE_FLAG_NEGOPT:
     813            if (opt_in_list(cp, fs->opts))
     814                return 0;
     815            break;
     816        case FS_TYPE_FLAG_OPT:
     817            if (!opt_in_list(cp, fs->opts))
     818                return 0;
     819            break;
     820        }
     821        n++;
     822    }
     823    if (checked_type == 0)
     824        return 1;
     825
     826    return (fs_type_negated ? !ret : ret);
     827}
     828
     829/* Check if we should ignore this filesystem. */
     830static int ignore(struct fs_info *fs)
     831{
     832    /*
     833     * If the pass number is 0, ignore it.
     834     */
     835    if (fs->passno == 0)
     836        return 1;
     837
     838    /*
     839     * If a specific fstype is specified, and it doesn't match,
     840     * ignore it.
     841     */
     842    if (!fs_match(fs))
     843        return 1;
     844
     845    /* Are we ignoring this type? */
     846    if (index_in_strings(ignored_types, fs->type) >= 0)
     847        return 1;
     848
     849    /* We can and want to check this file system type. */
     850    return 0;
     851}
     852
    1064853/* Check all file systems, using the /etc/fstab table. */
    1065854static int check_all(void)
    1066855{
    1067     struct fs_info *fs = NULL;
     856    struct fs_info *fs;
    1068857    int status = EXIT_OK;
    1069     int not_done_yet = 1;
    1070     int passno = 1;
    1071     int pass_done;
     858    smallint not_done_yet;
     859    smallint pass_done;
     860    int passno;
    1072861
    1073862    if (verbose)
    1074         fputs("Checking all file systems.\n", stdout);
     863        puts("Checking all filesystems");
    1075864
    1076865    /*
     
    1089878    if (!parallel_root) {
    1090879        for (fs = filesys_info; fs; fs = fs->next) {
    1091             if (!strcmp(fs->mountpt, "/"))
     880            if (LONE_CHAR(fs->mountpt, '/'))
    1092881                break;
    1093882        }
     
    1104893    /*
    1105894     * This is for the bone-headed user who enters the root
    1106      * filesystem twice.  Skip root will skep all root entries.
     895     * filesystem twice.  Skip root will skip all root entries.
    1107896     */
    1108897    if (skip_root)
    1109898        for (fs = filesys_info; fs; fs = fs->next)
    1110             if (!strcmp(fs->mountpt, "/"))
     899            if (LONE_CHAR(fs->mountpt, '/'))
    1111900                fs->flags |= FLAG_DONE;
    1112901
     902    not_done_yet = 1;
     903    passno = 1;
    1113904    while (not_done_yet) {
    1114905        not_done_yet = 0;
     
    1126917             */
    1127918            if (fs->passno > passno) {
    1128                 not_done_yet++;
     919                not_done_yet = 1;
    1129920                continue;
    1130921            }
     
    1149940             * at one time, apply that limit.
    1150941             */
    1151             if (serialize ||
    1152                 (max_running && (num_running >= max_running))) {
     942            if (serialize
     943             || (max_running && (num_running >= max_running))
     944            ) {
    1153945                pass_done = 0;
    1154946                break;
     
    1163955        if (pass_done) {
    1164956            if (verbose > 1)
    1165                 printf("----------------------------------\n");
     957                puts("----------------------------------");
    1166958            passno++;
    1167959        } else
    1168             not_done_yet++;
    1169     }
    1170     if (cancel_requested && !kill_sent) {
    1171         kill_all(SIGTERM);
    1172         kill_sent++;
    1173     }
     960            not_done_yet = 1;
     961    }
     962    kill_all_if_cancel_requested();
    1174963    status |= wait_many(FLAG_WAIT_ATLEAST_ONE);
    1175964    return status;
    1176965}
    1177966
    1178 static void signal_cancel(int sig FSCK_ATTR((unused)))
    1179 {
    1180     cancel_requested++;
    1181 }
    1182 
    1183 static void PRS(int argc, char *argv[])
    1184 {
    1185     int     i, j;
    1186     char    *arg, *dev, *tmp = 0;
    1187     char    options[128];
    1188     int     opt = 0;
    1189     int     opts_for_fsck = 0;
    1190     struct sigaction        sa;
    1191 
    1192     /*
    1193      * Set up signal action
    1194      */
    1195     memset(&sa, 0, sizeof(struct sigaction));
    1196     sa.sa_handler = signal_cancel;
    1197     sigaction(SIGINT, &sa, 0);
    1198     sigaction(SIGTERM, &sa, 0);
    1199 
     967/*
     968 * Deal with the fsck -t argument.
     969 * Huh, for mount "-t novfat,nfs" means "neither vfat nor nfs"!
     970 * Why here we require "-t novfat,nonfs" ??
     971 */
     972static void compile_fs_type(char *fs_type)
     973{
     974    char *s;
     975    int num = 2;
     976    smallint negate;
     977
     978    if (fs_type) {
     979        s = fs_type;
     980        while ((s = strchr(s, ','))) {
     981            num++;
     982            s++;
     983        }
     984    }
     985
     986    fs_type_list = xzalloc(num * sizeof(fs_type_list[0]));
     987    fs_type_flag = xzalloc(num * sizeof(fs_type_flag[0]));
     988    fs_type_negated = -1; /* not yet known is it negated or not */
     989
     990    if (!fs_type)
     991        return;
     992
     993    num = 0;
     994    s = fs_type;
     995    while (1) {
     996        char *comma;
     997
     998        negate = 0;
     999        if (s[0] == 'n' && s[1] == 'o') { /* "no.." */
     1000            s += 2;
     1001            negate = 1;
     1002        } else if (s[0] == '!') {
     1003            s++;
     1004            negate = 1;
     1005        }
     1006
     1007        if (strcmp(s, "loop") == 0)
     1008            /* loop is really short-hand for opts=loop */
     1009            goto loop_special_case;
     1010        if (strncmp(s, "opts=", 5) == 0) {
     1011            s += 5;
     1012 loop_special_case:
     1013            fs_type_flag[num] = negate ? FS_TYPE_FLAG_NEGOPT : FS_TYPE_FLAG_OPT;
     1014        } else {
     1015            if (fs_type_negated == -1)
     1016                fs_type_negated = negate;
     1017            if (fs_type_negated != negate)
     1018                bb_error_msg_and_die(
     1019"either all or none of the filesystem types passed to -t must be prefixed "
     1020"with 'no' or '!'");
     1021        }
     1022        comma = strchr(s, ',');
     1023        fs_type_list[num++] = comma ? xstrndup(s, comma-s) : xstrdup(s);
     1024        if (!comma)
     1025            break;
     1026        s = comma + 1;
     1027    }
     1028}
     1029
     1030static void parse_args(int argc, char **argv)
     1031{
     1032    int i, j;
     1033    char *arg, *tmp;
     1034    char *options = NULL;
     1035    int optpos = 0;
     1036    int opts_for_fsck = 0;
     1037
     1038    /* in bss, so already zeroed
    12001039    num_devices = 0;
    12011040    num_args = 0;
    1202     instance_list = 0;
    1203 
    1204     for (i=1; i < argc; i++) {
     1041    instance_list = NULL;
     1042    */
     1043
     1044/* TODO: getopt32 */
     1045    for (i = 1; i < argc; i++) {
    12051046        arg = argv[i];
    1206         if (!arg)
     1047
     1048        /* "/dev/blk" or "/path" or "UUID=xxx" or "LABEL=xxx" */
     1049        if ((arg[0] == '/' && !opts_for_fsck) || strchr(arg, '=')) {
     1050// FIXME: must check that arg is a blkdev, or resolve
     1051// "/path", "UUID=xxx" or "LABEL=xxx" into block device name
     1052// ("UUID=xxx"/"LABEL=xxx" can probably shifted to fsck.auto duties)
     1053            devices = xrealloc(devices, (num_devices+1) * sizeof(devices[0]));
     1054            devices[num_devices++] = xstrdup(arg);
    12071055            continue;
    1208         if ((arg[0] == '/' && !opts_for_fsck) || strchr(arg, '=')) {
    1209             if (num_devices >= MAX_DEVICES) {
    1210                 bb_error_msg_and_die("too many devices");
    1211             }
    1212             dev = blkid_get_devname(cache, arg, NULL);
    1213             if (!dev && strchr(arg, '=')) {
    1214                 /*
    1215                  * Check to see if we failed because
    1216                  * /proc/partitions isn't found.
    1217                  */
    1218                 if (access("/proc/partitions", R_OK) < 0) {
    1219                     bb_error_msg_and_die("Couldn't open /proc/partitions: %m\n"
    1220                             "Is /proc mounted?");
    1221                 }
    1222                 /*
    1223                  * Check to see if this is because
    1224                  * we're not running as root
    1225                  */
    1226                 if (geteuid())
    1227                     bb_error_msg_and_die(
    1228         "Must be root to scan for matching filesystems: %s\n", arg);
    1229                 else
    1230                     bb_error_msg_and_die(
    1231         "Couldn't find matching filesystem: %s", arg);
    1232             }
    1233             devices[num_devices++] = dev ? dev : string_copy(arg);
     1056        }
     1057
     1058        if (arg[0] != '-' || opts_for_fsck) {
     1059            args = xrealloc(args, (num_args+1) * sizeof(args[0]));
     1060            args[num_args++] = xstrdup(arg);
    12341061            continue;
    12351062        }
    1236         if (arg[0] != '-' || opts_for_fsck) {
    1237             if (num_args >= MAX_ARGS) {
    1238                 bb_error_msg_and_die("too many arguments");
    1239             }
    1240             args[num_args++] = string_copy(arg);
    1241             continue;
    1242         }
    1243         for (j=1; arg[j]; j++) {
     1063
     1064        for (j = 1; arg[j]; j++) {
    12441065            if (opts_for_fsck) {
    1245                 options[++opt] = arg[j];
     1066                optpos++;
     1067                /* one extra for '\0' */
     1068                options = xrealloc(options, optpos + 2);
     1069                options[optpos] = arg[j];
    12461070                continue;
    12471071            }
    12481072            switch (arg[j]) {
    12491073            case 'A':
    1250                 doall++;
    1251                 break;
     1074                doall = 1;
     1075                break;
     1076#if DO_PROGRESS_INDICATOR
    12521077            case 'C':
    1253                 progress++;
    1254                 if (arg[j+1]) {
    1255                     progress_fd = string_to_int(arg+j+1);
    1256                     if (progress_fd < 0)
    1257                         progress_fd = 0;
    1258                     else
    1259                         goto next_arg;
    1260                 } else if ((i+1) < argc &&
    1261                        !strncmp(argv[i+1], "-", 1) == 0) {
    1262                     progress_fd = string_to_int(argv[i]);
    1263                     if (progress_fd < 0)
    1264                         progress_fd = 0;
    1265                     else {
    1266                         goto next_arg;
    1267                         i++;
    1268                     }
     1078                progress = 1;
     1079                if (arg[++j]) { /* -Cn */
     1080                    progress_fd = xatoi_u(&arg[j]);
     1081                    goto next_arg;
    12691082                }
    1270                 break;
     1083                /* -C n */
     1084                progress_fd = xatoi_u(argv[++i]);
     1085                goto next_arg;
     1086#endif
    12711087            case 'V':
    12721088                verbose++;
    12731089                break;
    12741090            case 'N':
    1275                 noexecute++;
     1091                noexecute = 1;
    12761092                break;
    12771093            case 'R':
    1278                 skip_root++;
     1094                skip_root = 1;
    12791095                break;
    12801096            case 'T':
    1281                 notitle++;
    1282                 break;
    1283             case 'M':
    1284                 like_mount++;
    1285                 break;
     1097                notitle = 1;
     1098                break;
     1099/*          case 'M':
     1100                like_mount = 1;
     1101                break; */
    12861102            case 'P':
    1287                 parallel_root++;
     1103                parallel_root = 1;
    12881104                break;
    12891105            case 's':
    1290                 serialize++;
     1106                serialize = 1;
    12911107                break;
    12921108            case 't':
    1293                 tmp = 0;
    12941109                if (fstype)
    12951110                    bb_show_usage();
    1296                 if (arg[j+1])
    1297                     tmp = arg+j+1;
    1298                 else if ((i+1) < argc)
    1299                     tmp = argv[++i];
     1111                if (arg[++j])
     1112                    tmp = &arg[j];
     1113                else if (++i < argc)
     1114                    tmp = argv[i];
    13001115                else
    13011116                    bb_show_usage();
    1302                 fstype = string_copy(tmp);
    1303                 compile_fs_type(fstype, &fs_type_compiled);
     1117                fstype = xstrdup(tmp);
     1118                compile_fs_type(fstype);
    13041119                goto next_arg;
    13051120            case '-':
     
    13101125                break;
    13111126            default:
    1312                 options[++opt] = arg[j];
     1127                optpos++;
     1128                /* one extra for '\0' */
     1129                options = xrealloc(options, optpos + 2);
     1130                options[optpos] = arg[j];
    13131131                break;
    13141132            }
    13151133        }
    1316     next_arg:
    1317         if (opt) {
     1134 next_arg:
     1135        if (optpos) {
    13181136            options[0] = '-';
    1319             options[++opt] = '\0';
    1320             if (num_args >= MAX_ARGS) {
    1321                 bb_error_msg("too many arguments");
    1322             }
    1323             args[num_args++] = string_copy(options);
    1324             opt = 0;
     1137            options[optpos + 1] = '\0';
     1138            args = xrealloc(args, (num_args+1) * sizeof(args[0]));
     1139            args[num_args++] = options;
     1140            optpos = 0;
     1141            options = NULL;
    13251142        }
    13261143    }
    13271144    if (getenv("FSCK_FORCE_ALL_PARALLEL"))
    1328         force_all_parallel++;
    1329     if ((tmp = getenv("FSCK_MAX_INST")))
    1330         max_running = atoi(tmp);
    1331 }
    1332 
    1333 int fsck_main(int argc, char *argv[])
     1145        force_all_parallel = 1;
     1146    tmp = getenv("FSCK_MAX_INST");
     1147    if (tmp)
     1148        max_running = xatoi(tmp);
     1149}
     1150
     1151static void signal_cancel(int sig ATTRIBUTE_UNUSED)
     1152{
     1153    cancel_requested = 1;
     1154}
     1155
     1156int fsck_main(int argc, char **argv);
     1157int fsck_main(int argc, char **argv)
    13341158{
    13351159    int i, status = 0;
    1336     int interactive = 0;
     1160    int interactive;
    13371161    const char *fstab;
    13381162    struct fs_info *fs;
    1339 
    1340     setvbuf(stdout, NULL, _IONBF, BUFSIZ);
    1341     setvbuf(stderr, NULL, _IONBF, BUFSIZ);
    1342 
    1343     blkid_get_cache(&cache, NULL);
    1344     PRS(argc, argv);
     1163    struct sigaction sa;
     1164
     1165    memset(&sa, 0, sizeof(sa));
     1166    sa.sa_handler = signal_cancel;
     1167    sigaction(SIGINT, &sa, 0);
     1168    sigaction(SIGTERM, &sa, 0);
     1169
     1170    setbuf(stdout, NULL);
     1171
     1172    parse_args(argc, argv);
    13451173
    13461174    if (!notitle)
    1347         printf("fsck %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE);
    1348 
     1175        puts("fsck (busybox "BB_VER", "BB_BT")");
     1176
     1177    /* Even plain "fsck /dev/hda1" needs fstab to get fs type,
     1178     * so we are scanning it anyway */
    13491179    fstab = getenv("FSTAB_FILE");
    13501180    if (!fstab)
    1351         fstab = _PATH_MNTTAB;
     1181        fstab = "/etc/fstab";
    13521182    load_fs_info(fstab);
    13531183
    1354     fsck_path = e2fs_set_sbin_path();
    1355 
    1356     if ((num_devices == 1) || (serialize))
    1357         interactive = 1;
     1184    interactive = (num_devices == 1) | serialize;
    13581185
    13591186    /* If -A was specified ("check all"), do that! */
     
    13621189
    13631190    if (num_devices == 0) {
    1364         serialize++;
    1365         interactive++;
     1191        serialize = 1;
     1192        interactive = 1;
    13661193        return check_all();
    13671194    }
    1368     for (i = 0 ; i < num_devices; i++) {
     1195
     1196    for (i = 0; i < num_devices; i++) {
    13691197        if (cancel_requested) {
    1370             if (!kill_sent) {
    1371                 kill_all(SIGTERM);
    1372                 kill_sent++;
    1373             }
     1198            kill_all_if_cancel_requested();
    13741199            break;
    13751200        }
     1201
    13761202        fs = lookup(devices[i]);
    1377         if (!fs) {
    1378             fs = create_fs_device(devices[i], 0, "auto",
    1379                           0, -1, -1);
    1380             if (!fs)
    1381                 continue;
    1382         }
     1203        if (!fs)
     1204            fs = create_fs_device(devices[i], 0, "auto", 0, -1, -1);
    13831205        fsck_device(fs, interactive);
    1384         if (serialize ||
    1385             (max_running && (num_running >= max_running))) {
     1206
     1207        if (serialize
     1208         || (max_running && (num_running >= max_running))
     1209        ) {
    13861210            struct fsck_instance *inst;
    13871211
     
    13921216            }
    13931217            if (verbose > 1)
    1394                 printf("----------------------------------\n");
     1218                puts("----------------------------------");
    13951219        }
    13961220    }
    13971221    status |= wait_many(FLAG_WAIT_ALL);
    1398     blkid_put_cache(cache);
    13991222    return status;
    14001223}
  • branches/stable/mindi-busybox/e2fsprogs/lsattr.c

    r821 r1770  
     1/* vi: set sw=4 ts=4: */
    12/*
    23 * lsattr.c     - List file attributes on an ext2 file system
     
    1819 */
    1920
    20 #include <sys/types.h>
    21 #include <dirent.h>
    22 #include <errno.h>
    23 #include <fcntl.h>
    24 #include <getopt.h>
    25 #include <stdio.h>
    26 #include <unistd.h>
    27 #include <stdlib.h>
    28 #include <string.h>
    29 #include <sys/param.h>
    30 #include <sys/stat.h>
     21#include "libbb.h"
     22#include "e2fs_lib.h"
    3123
    32 #include "ext2fs/ext2_fs.h"
    33 #include "e2fsbb.h"
    34 #include "e2p/e2p.h"
    35 
    36 #define OPT_RECUR 1
    37 #define OPT_ALL 2
    38 #define OPT_DIRS_OPT 4
    39 #define OPT_PF_LONG 8
    40 #define OPT_GENERATION 16
    41 static int flags;
    42 
    43 #ifdef CONFIG_LFS
    44 # define LSTAT lstat64
    45 # define STRUCT_STAT struct stat64
    46 #else
    47 # define LSTAT lstat
    48 # define STRUCT_STAT struct stat
    49 #endif
     24enum {
     25    OPT_RECUR      = 0x1,
     26    OPT_ALL        = 0x2,
     27    OPT_DIRS_OPT   = 0x4,
     28    OPT_PF_LONG    = 0x8,
     29    OPT_GENERATION = 0x10,
     30};
    5031
    5132static void list_attributes(const char *name)
     
    5435    unsigned long generation;
    5536
    56     if (fgetflags(name, &fsflags) == -1)
     37    if (fgetflags(name, &fsflags) != 0)
    5738        goto read_err;
    58     if (flags & OPT_GENERATION) {
    59         if (fgetversion(name, &generation) == -1)
     39
     40    if (option_mask32 & OPT_GENERATION) {
     41        if (fgetversion(name, &generation) != 0)
    6042            goto read_err;
    6143        printf("%5lu ", generation);
    6244    }
    6345
    64     if (flags & OPT_PF_LONG) {
     46    if (option_mask32 & OPT_PF_LONG) {
    6547        printf("%-28s ", name);
    6648        print_flags(stdout, fsflags, PFOPT_LONG);
    67         printf("\n");
     49        puts("");
    6850    } else {
    6951        print_flags(stdout, fsflags, 0);
     
    7254
    7355    return;
    74 read_err:
     56 read_err:
    7557    bb_perror_msg("reading %s", name);
    76 }
    77 
    78 static int lsattr_dir_proc(const char *, struct dirent *, void *);
    79 
    80 static void lsattr_args(const char *name)
    81 {
    82     STRUCT_STAT st;
    83 
    84     if (LSTAT(name, &st) == -1) {
    85         bb_perror_msg("stating %s", name);
    86     } else {
    87         if (S_ISDIR(st.st_mode) && !(flags & OPT_DIRS_OPT))
    88             iterate_on_dir(name, lsattr_dir_proc, NULL);
    89         else
    90             list_attributes(name);
    91     }
    9258}
    9359
     
    9561               void *private)
    9662{
    97     STRUCT_STAT st;
     63    struct stat st;
    9864    char *path;
    9965
    10066    path = concat_path_file(dir_name, de->d_name);
    10167
    102     if (LSTAT(path, &st) == -1)
    103         bb_perror_msg(path);
    104     else {
    105         if (de->d_name[0] != '.' || (flags & OPT_ALL)) {
    106             list_attributes(path);
    107             if (S_ISDIR(st.st_mode) && (flags & OPT_RECUR) &&
    108                (de->d_name[0] != '.' && (de->d_name[1] != '\0' ||
    109                (de->d_name[1] != '.' && de->d_name[2] != '\0')))) {
    110                 printf("\n%s:\n", path);
    111                 iterate_on_dir(path, lsattr_dir_proc, NULL);
    112                 printf("\n");
    113             }
     68    if (lstat(path, &st) != 0)
     69        bb_perror_msg("stat %s", path);
     70    else if (de->d_name[0] != '.' || (option_mask32 & OPT_ALL)) {
     71        list_attributes(path);
     72        if (S_ISDIR(st.st_mode) && (option_mask32 & OPT_RECUR)
     73         && !DOT_OR_DOTDOT(de->d_name)
     74        ) {
     75            printf("\n%s:\n", path);
     76            iterate_on_dir(path, lsattr_dir_proc, NULL);
     77            puts("");
    11478        }
    11579    }
    11680
    11781    free(path);
    118 
    11982    return 0;
    12083}
    12184
     85static void lsattr_args(const char *name)
     86{
     87    struct stat st;
     88
     89    if (lstat(name, &st) == -1) {
     90        bb_perror_msg("stat %s", name);
     91    } else if (S_ISDIR(st.st_mode) && !(option_mask32 & OPT_DIRS_OPT)) {
     92        iterate_on_dir(name, lsattr_dir_proc, NULL);
     93    } else {
     94        list_attributes(name);
     95    }
     96}
     97
     98int lsattr_main(int argc, char **argv);
    12299int lsattr_main(int argc, char **argv)
    123100{
    124     int i;
     101    getopt32(argv, "Radlv");
     102    argv += optind;
    125103
    126     flags = bb_getopt_ulflags(argc, argv, "Radlv");
    127 
    128     if (optind > argc - 1)
     104    if (!*argv)
    129105        lsattr_args(".");
    130     else
    131         for (i = optind; i < argc; i++)
    132             lsattr_args(argv[i]);
     106    else {
     107        while (*argv)
     108            lsattr_args(*argv++);
     109    }
    133110
    134111    return EXIT_SUCCESS;
Note: See TracChangeset for help on using the changeset viewer.