Bump to version 1.22.1
[platform/upstream/busybox.git] / util-linux / fsck_minix.c
index 3ebc076..33767a1 100644 (file)
@@ -4,7 +4,7 @@
  *
  * (C) 1991, 1992 Linus Torvalds.
  *
- * Licensed under GPLv2, see file LICENSE in this tarball for details.
+ * Licensed under GPLv2, see file LICENSE in this source tree.
  */
 
 /*
@@ -13,7 +13,7 @@
  * 10.11.91  -  updated, does checking, no repairs yet.
  *             Sent out to the mailing-list for testing.
  *
- * 14.11.91  - Testing seems to have gone well. Added some
+ * 14.11.91  -  Testing seems to have gone well. Added some
  *             correction-code, and changed some functions.
  *
  * 15.11.91  -  More correction code. Hopefully it notices most
  * 16.11.91  -  More corrections (thanks to Mika Jalava). Most
  *             things seem to work now. Yeah, sure.
  *
- *
- * 19.04.92  - Had to start over again from this old version, as a
+ * 19.04.92  -  Had to start over again from this old version, as a
  *             kernel bug ate my enhanced fsck in february.
  *
- * 28.02.93  - added support for different directory entry sizes..
+ * 28.02.93  -  added support for different directory entry sizes..
  *
  * Sat Mar  6 18:59:42 1993, faith@cs.unc.edu: Output namelen with
- *                           super-block information
+ *                           superblock information
  *
  * Sat Oct  9 11:17:11 1993, faith@cs.unc.edu: make exit status conform
  *                           to that required by fsutil
  *
  * Mon Jan  3 11:06:52 1994 - Dr. Wettstein (greg%wind.uucp@plains.nodak.edu)
- *                           Added support for file system valid flag.  Also
- *                           added program_version variable and output of
- *                           program name and version number when program
- *                           is executed.
+ *                            Added support for file system valid flag.  Also
+ *                            added program_version variable and output of
+ *                            program name and version number when program
+ *                            is executed.
  *
- * 30.10.94 - added support for v2 filesystem
- *            (Andreas Schwab, schwab@issan.informatik.uni-dortmund.de)
+ * 30.10.94  - added support for v2 filesystem
+ *             (Andreas Schwab, schwab@issan.informatik.uni-dortmund.de)
  *
- * 10.12.94  -  added test to prevent checking of mounted fs adapted
- *              from Theodore Ts'o's (tytso@athena.mit.edu) e2fsck
- *              program.  (Daniel Quinlan, quinlan@yggdrasil.com)
+ * 10.12.94  - added test to prevent checking of mounted fs adapted
+ *             from Theodore Ts'o's (tytso@athena.mit.edu) e2fsck
+ *             program.  (Daniel Quinlan, quinlan@yggdrasil.com)
  *
  * 01.07.96  - Fixed the v2 fs stuff to use the right #defines and such
- *            for modern libcs (janl@math.uio.no, Nicolai Langfeldt)
+ *             for modern libcs (janl@math.uio.no, Nicolai Langfeldt)
  *
  * 02.07.96  - Added C bit fiddling routines from rmk@ecs.soton.ac.uk
  *             (Russell King).  He made them for ARM.  It would seem
- *            that the ARM is powerful enough to do this in C whereas
+ *             that the ARM is powerful enough to do this in C whereas
  *             i386 and m64k must use assembly to get it fast >:-)
- *            This should make minix fsck system-independent.
- *            (janl@math.uio.no, Nicolai Langfeldt)
+ *             This should make minix fsck system-independent.
+ *             (janl@math.uio.no, Nicolai Langfeldt)
  *
  * 04.11.96  - Added minor fixes from Andreas Schwab to avoid compiler
  *             warnings.  Added mc68k bitops from
- *            Joerg Dorchain <dorchain@mpi-sb.mpg.de>.
+ *             Joerg Dorchain <dorchain@mpi-sb.mpg.de>.
  *
  * 06.11.96  - Added v2 code submitted by Joerg Dorchain, but written by
  *             Andreas Schwab.
@@ -79,7 +78,7 @@
  *     -a for automatic repairs (not implemented)
  *     -r for repairs (interactive) (not implemented)
  *     -v for verbose (tells how many files)
- *     -s for super-block info
+ *     -s for superblock info
  *     -m for minix-like "mode not cleared" warnings
  *     -f force filesystem check even if filesystem marked as valid
  *
  * enforced (but it's not much fun on a character device :-).
  */
 
+//usage:#define fsck_minix_trivial_usage
+//usage:       "[-larvsmf] BLOCKDEV"
+//usage:#define fsck_minix_full_usage "\n\n"
+//usage:       "Check MINIX filesystem\n"
+//usage:     "\n       -l      List all filenames"
+//usage:     "\n       -r      Perform interactive repairs"
+//usage:     "\n       -a      Perform automatic repairs"
+//usage:     "\n       -v      Verbose"
+//usage:     "\n       -s      Output superblock information"
+//usage:     "\n       -m      Show \"mode not cleared\" warnings"
+//usage:     "\n       -f      Force file system check"
+
 #include <mntent.h>
 #include "libbb.h"
 #include "minix.h"
@@ -121,8 +132,9 @@ enum { version2 = 0 };
 
 enum { MAX_DEPTH = 32 };
 
+enum { dev_fd = 3 };
+
 struct globals {
-       int dev_fd;
 #if ENABLE_FEATURE_MINIX2
        smallint version2;
 #endif
@@ -147,18 +159,16 @@ struct globals {
 
        /* Bigger stuff */
        struct termios sv_termios;
-       char super_block_buffer[BLOCK_SIZE];
+       char superblock_buffer[BLOCK_SIZE];
        char add_zone_ind_blk[BLOCK_SIZE];
        char add_zone_dind_blk[BLOCK_SIZE];
-       USE_FEATURE_MINIX2(char add_zone_tind_blk[BLOCK_SIZE];)
+       IF_FEATURE_MINIX2(char add_zone_tind_blk[BLOCK_SIZE];)
        char check_file_blk[BLOCK_SIZE];
 
        /* File-name data */
        char current_name[MAX_DEPTH * MINIX_NAME_MAX];
 };
-
 #define G (*ptr_to_globals)
-#define dev_fd             (G.dev_fd             )
 #if ENABLE_FEATURE_MINIX2
 #define version2           (G.version2           )
 #endif
@@ -183,7 +193,7 @@ struct globals {
 #define name_depth         (G.name_depth         )
 #define name_component     (G.name_component     )
 #define sv_termios         (G.sv_termios         )
-#define super_block_buffer (G.super_block_buffer )
+#define superblock_buffer  (G.superblock_buffer )
 #define add_zone_ind_blk   (G.add_zone_ind_blk   )
 #define add_zone_dind_blk  (G.add_zone_dind_blk  )
 #define add_zone_tind_blk  (G.add_zone_tind_blk  )
@@ -223,7 +233,7 @@ enum {
 #define Inode1 (((struct minix1_inode *) inode_buffer)-1)
 #define Inode2 (((struct minix2_inode *) inode_buffer)-1)
 
-#define Super (*(struct minix_super_block *)(super_block_buffer))
+#define Super (*(struct minix_superblock *)(superblock_buffer))
 
 #if ENABLE_FEATURE_MINIX2
 # define ZONES    ((unsigned)(version2 ? Super.s_zones : Super.s_nzones))
@@ -244,15 +254,15 @@ static ALWAYS_INLINE unsigned div_roundup(unsigned size, unsigned n)
        return (size + n-1) / n;
 }
 
-#if ENABLE_FEATURE_MINIX2
-#define INODE_BLOCKS div_roundup(INODES, (version2 ? MINIX2_INODES_PER_BLOCK \
-                                   : MINIX1_INODES_PER_BLOCK))
+#if !ENABLE_FEATURE_MINIX2
+#define INODE_BLOCKS            div_roundup(INODES, MINIX1_INODES_PER_BLOCK)
 #else
-#define INODE_BLOCKS div_roundup(INODES, MINIX1_INODES_PER_BLOCK)
+#define INODE_BLOCKS            div_roundup(INODES, \
+                                (version2 ? MINIX2_INODES_PER_BLOCK : MINIX1_INODES_PER_BLOCK))
 #endif
 
-#define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE)
-#define NORM_FIRSTZONE    (2 + IMAPS + ZMAPS + INODE_BLOCKS)
+#define INODE_BUFFER_SIZE       (INODE_BLOCKS * BLOCK_SIZE)
+#define NORM_FIRSTZONE          (2 + IMAPS + ZMAPS + INODE_BLOCKS)
 
 /* Before you ask "where they come from?": */
 /* setbit/clrbit are supplied by sys/param.h */
@@ -289,11 +299,11 @@ static void recursive_check(unsigned ino);
 static void recursive_check2(unsigned ino);
 #endif
 
-static void die(const char *str) ATTRIBUTE_NORETURN;
+static void die(const char *str) NORETURN;
 static void die(const char *str)
 {
        if (termios_set)
-               tcsetattr(0, TCSANOW, &sv_termios);
+               tcsetattr_stdin_TCSANOW(&sv_termios);
        bb_error_msg_and_die("%s", str);
 }
 
@@ -341,22 +351,24 @@ static int ask(const char *string, int def)
        }
        printf(def ? "%s (y/n)? " : "%s (n/y)? ", string);
        for (;;) {
-               fflush(stdout);
+               fflush_all();
                c = getchar();
                if (c == EOF) {
                        if (!def)
                                errors_uncorrected = 1;
                        return def;
                }
-               c = toupper(c);
-               if (c == 'Y') {
+               if (c == '\n')
+                       break;
+               c |= 0x20; /* tolower */
+               if (c == 'y') {
                        def = 1;
                        break;
-               } else if (c == 'N') {
+               }
+               if (c == 'n') {
                        def = 0;
                        break;
-               } else if (c == ' ' || c == '\n')
-                       break;
+               }
        }
        if (def)
                printf("y\n");
@@ -374,38 +386,28 @@ static int ask(const char *string, int def)
  */
 static void check_mount(void)
 {
-       FILE *f;
-       struct mntent *mnt;
-       int cont;
-       int fd;
-//XXX:FIXME use find_mount_point()
-       f = setmntent(MOUNTED, "r");
-       if (f == NULL)
-               return;
-       while ((mnt = getmntent(f)) != NULL)
-               if (strcmp(device_name, mnt->mnt_fsname) == 0)
-                       break;
-       endmntent(f);
-       if (!mnt)
-               return;
-
-       /*
-        * If the root is mounted read-only, then /etc/mtab is
-        * probably not correct; so we won't issue a warning based on
-        * it.
-        */
-       fd = open(MOUNTED, O_RDWR);
-       if (fd < 0 && errno == EROFS)
-               return;
-       close(fd);
-
-       printf("%s is mounted. ", device_name);
-       cont = 0;
-       if (isatty(0) && isatty(1))
-               cont = ask("Do you really want to continue", 0);
-       if (!cont) {
-               printf("Check aborted\n");
-               exit(EXIT_SUCCESS);
+       if (find_mount_point(device_name, 0)) {
+               int cont;
+#if ENABLE_FEATURE_MTAB_SUPPORT
+               /*
+                * If the root is mounted read-only, then /etc/mtab is
+                * probably not correct; so we won't issue a warning based on
+                * it.
+                */
+               int fd = open(bb_path_mtab_file, O_RDWR);
+
+               if (fd < 0 && errno == EROFS)
+                       return;
+               close(fd);
+#endif
+               printf("%s is mounted. ", device_name);
+               cont = 0;
+               if (isatty(0) && isatty(1))
+                       cont = ask("Do you really want to continue", 0);
+               if (!cont) {
+                       printf("Check aborted\n");
+                       exit(EXIT_SUCCESS);
+               }
        }
 }
 
@@ -560,7 +562,7 @@ static int map_block2(struct minix2_inode *inode, unsigned blknr)
 }
 #endif
 
-static void write_super_block(void)
+static void write_superblock(void)
 {
        /*
         * Set the state of the filesystem based on whether or not there
@@ -572,20 +574,20 @@ static void write_super_block(void)
                Super.s_state &= ~MINIX_ERROR_FS;
 
        xlseek(dev_fd, BLOCK_SIZE, SEEK_SET);
-       if (BLOCK_SIZE != full_write(dev_fd, super_block_buffer, BLOCK_SIZE))
-               die("cannot write super-block");
+       if (BLOCK_SIZE != full_write(dev_fd, superblock_buffer, BLOCK_SIZE))
+               die("can't write superblock");
 }
 
 static void write_tables(void)
 {
-       write_super_block();
+       write_superblock();
 
        if (IMAPS * BLOCK_SIZE != write(dev_fd, inode_map, IMAPS * BLOCK_SIZE))
-               die("cannot write inode map");
+               die("can't write inode map");
        if (ZMAPS * BLOCK_SIZE != write(dev_fd, zone_map, ZMAPS * BLOCK_SIZE))
-               die("cannot write zone map");
+               die("can't write zone map");
        if (INODE_BUFFER_SIZE != write(dev_fd, inode_buffer, INODE_BUFFER_SIZE))
-               die("cannot write inodes");
+               die("can't write inodes");
 }
 
 static void get_dirsize(void)
@@ -614,8 +616,8 @@ static void get_dirsize(void)
 static void read_superblock(void)
 {
        xlseek(dev_fd, BLOCK_SIZE, SEEK_SET);
-       if (BLOCK_SIZE != full_read(dev_fd, super_block_buffer, BLOCK_SIZE))
-               die("cannot read super block");
+       if (BLOCK_SIZE != full_read(dev_fd, superblock_buffer, BLOCK_SIZE))
+               die("can't read superblock");
        /* already initialized to:
        namelen = 14;
        dirsize = 16;
@@ -634,13 +636,13 @@ static void read_superblock(void)
                version2 = 1;
 #endif
        } else
-               die("bad magic number in super-block");
+               die("bad magic number in superblock");
        if (ZONESIZE != 0 || BLOCK_SIZE != 1024)
                die("only 1k blocks/zones supported");
        if (IMAPS * BLOCK_SIZE * 8 < INODES + 1)
-               die("bad s_imap_blocks field in super-block");
+               die("bad s_imap_blocks field in superblock");
        if (ZMAPS * BLOCK_SIZE * 8 < ZONES - FIRSTZONE + 1)
-               die("bad s_zmap_blocks field in super-block");
+               die("bad s_zmap_blocks field in superblock");
 }
 
 static void read_tables(void)
@@ -651,11 +653,11 @@ static void read_tables(void)
        inode_count = xmalloc(INODES + 1);
        zone_count = xmalloc(ZONES);
        if (IMAPS * BLOCK_SIZE != read(dev_fd, inode_map, IMAPS * BLOCK_SIZE))
-               die("cannot read inode map");
+               die("can't read inode map");
        if (ZMAPS * BLOCK_SIZE != read(dev_fd, zone_map, ZMAPS * BLOCK_SIZE))
-               die("cannot read zone map");
+               die("can't read zone map");
        if (INODE_BUFFER_SIZE != read(dev_fd, inode_buffer, INODE_BUFFER_SIZE))
-               die("cannot read inodes");
+               die("can't read inodes");
        if (NORM_FIRSTZONE != FIRSTZONE) {
                printf("warning: firstzone!=norm_firstzone\n");
                errors_uncorrected = 1;
@@ -684,7 +686,7 @@ static void get_inode_common(unsigned nr, uint16_t i_mode)
        total++;
        if (!inode_count[nr]) {
                if (!inode_in_use(nr)) {
-                       printf("Inode %d is marked as 'unused', but it is used "
+                       printf("Inode %u is marked as 'unused', but it is used "
                                        "for file '%s'\n", nr, current_name);
                        if (OPT_repair) {
                                if (ask("Mark as 'in use'", 1))
@@ -906,8 +908,12 @@ static void check_zones(unsigned i)
        if (inode_count[i] > 1)         /* have we counted this file already? */
                return;
        inode = Inode1 + i;
-       if (!S_ISDIR(inode->i_mode) && !S_ISREG(inode->i_mode) &&
-               !S_ISLNK(inode->i_mode)) return;
+       if (!S_ISDIR(inode->i_mode)
+        && !S_ISREG(inode->i_mode)
+        && !S_ISLNK(inode->i_mode)
+       ) {
+               return;
+       }
        for (i = 0; i < 7; i++)
                add_zone(i + inode->i_zone, &changed);
        add_zone_ind(7 + inode->i_zone, &changed);
@@ -1124,7 +1130,7 @@ static void check_counts(void)
                        continue;
                }
                printf("Zone %d: %sin use, counted=%d\n",
-                          i, zone_in_use(i) ? "" : "not ", zone_count[i]);
+                       i, zone_in_use(i) ? "" : "not ", zone_count[i]);
        }
 }
 
@@ -1176,7 +1182,7 @@ static void check_counts2(void)
                        continue;
                }
                printf("Zone %d: %sin use, counted=%d\n",
-                          i, zone_in_use(i) ? "" : "not ", zone_count[i]);
+                       i, zone_in_use(i) ? "" : "not ", zone_count[i]);
        }
 }
 #endif
@@ -1204,7 +1210,7 @@ void check2(void);
 #endif
 
 int fsck_minix_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
-int fsck_minix_main(int argc ATTRIBUTE_UNUSED, char **argv)
+int fsck_minix_main(int argc UNUSED_PARAM, char **argv)
 {
        struct termios tmp;
        int retcode = 0;
@@ -1223,7 +1229,7 @@ int fsck_minix_main(int argc ATTRIBUTE_UNUSED, char **argv)
                if (!isatty(0) || !isatty(1))
                        die("need terminal for interactive repairs");
        }
-       dev_fd = xopen(device_name, OPT_repair ? O_RDWR : O_RDONLY);
+       xmove_fd(xopen(device_name, OPT_repair ? O_RDWR : O_RDONLY), dev_fd);
 
        /*sync(); paranoia? */
        read_superblock();
@@ -1246,7 +1252,7 @@ int fsck_minix_main(int argc ATTRIBUTE_UNUSED, char **argv)
                printf("Forcing filesystem check on %s\n", device_name);
        else if (OPT_repair)
                printf("Filesystem on %s is dirty, needs checking\n",
-                          device_name);
+                       device_name);
 
        read_tables();
 
@@ -1254,7 +1260,7 @@ int fsck_minix_main(int argc ATTRIBUTE_UNUSED, char **argv)
                tcgetattr(0, &sv_termios);
                tmp = sv_termios;
                tmp.c_lflag &= ~(ICANON | ECHO);
-               tcsetattr(0, TCSANOW, &tmp);
+               tcsetattr_stdin_TCSANOW(&tmp);
                termios_set = 1;
        }
 
@@ -1273,33 +1279,33 @@ int fsck_minix_main(int argc ATTRIBUTE_UNUSED, char **argv)
                        if (!inode_in_use(i))
                                free_cnt++;
                printf("\n%6u inodes used (%u%%)\n", (INODES - free_cnt),
-                          100 * (INODES - free_cnt) / INODES);
+                       100 * (INODES - free_cnt) / INODES);
                for (i = FIRSTZONE, free_cnt = 0; i < ZONES; i++)
                        if (!zone_in_use(i))
                                free_cnt++;
                printf("%6u zones used (%u%%)\n\n"
-                          "%6u regular files\n"
-                          "%6u directories\n"
-                          "%6u character device files\n"
-                          "%6u block device files\n"
-                          "%6u links\n"
-                          "%6u symbolic links\n"
-                          "------\n"
-                          "%6u files\n",
-                          (ZONES - free_cnt), 100 * (ZONES - free_cnt) / ZONES,
-                          regular, directory, chardev, blockdev,
-                          links - 2 * directory + 1, symlinks,
-                          total - 2 * directory + 1);
+                       "%6u regular files\n"
+                       "%6u directories\n"
+                       "%6u character device files\n"
+                       "%6u block device files\n"
+                       "%6u links\n"
+                       "%6u symbolic links\n"
+                       "------\n"
+                       "%6u files\n",
+                       (ZONES - free_cnt), 100 * (ZONES - free_cnt) / ZONES,
+                       regular, directory, chardev, blockdev,
+                       links - 2 * directory + 1, symlinks,
+                       total - 2 * directory + 1);
        }
        if (changed) {
                write_tables();
                printf("FILE SYSTEM HAS BEEN CHANGED\n");
                sync();
        } else if (OPT_repair)
-               write_super_block();
+               write_superblock();
 
        if (OPT_manual)
-               tcsetattr(0, TCSANOW, &sv_termios);
+               tcsetattr_stdin_TCSANOW(&sv_termios);
 
        if (changed)
                retcode += 3;