ash: fix signal handling
[oweals/busybox.git] / util-linux / fsck_minix.c
index ebfd645f2a5b2a3ac0aeb9545b831a75c7bcc84a..cc73cdd5afdb98a482655d1e760ff4b4225e1300 100644 (file)
@@ -131,13 +131,19 @@ static int dirsize = 16;
 static int namelen = 14;
 
 static char *inode_buffer;
-//xzalloc?
-static char super_block_buffer[BLOCK_SIZE];
+
+static struct {
+       char super_block_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];)
+       char check_file_blk[BLOCK_SIZE];
+} *blockbuf;
 
 #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_super_block *)(blockbuf->super_block_buffer))
 
 #if ENABLE_FEATURE_MINIX2
 # define ZONES    ((unsigned)(version2 ? Super.s_zones : Super.s_nzones))
@@ -155,7 +161,7 @@ static char super_block_buffer[BLOCK_SIZE];
 /* gcc likes this more (code is smaller) than macro variant */
 static ATTRIBUTE_ALWAYS_INLINE unsigned div_roundup(unsigned size, unsigned n)
 {
-        return (size + n-1) / n;
+       return (size + n-1) / n;
 }
 
 #if ENABLE_FEATURE_MINIX2
@@ -174,38 +180,47 @@ static char *zone_map;
 static unsigned char *inode_count;
 static unsigned char *zone_count;
 
-static int bit(char *a, unsigned int i)
+/* Before you ask "where they come from?": */
+/* setbit/clrbit are supplied by sys/param.h */
+
+static int minix_bit(const char *a, unsigned i)
+{
+       return (a[i >> 3] & (1<<(i & 7)));
+}
+
+static void minix_setbit(char *a, unsigned i)
+{
+       setbit(a, i);
+       changed = 1;
+}
+static void minix_clrbit(char *a, unsigned i)
 {
-         return (a[i >> 3] & (1<<(i & 7))) != 0;
+       clrbit(a, i);
+       changed = 1;
 }
 
-#define inode_in_use(x) (bit(inode_map,(x)))
-#define zone_in_use(x) (bit(zone_map,(x)-FIRSTZONE+1))
+/* Note: do not assume 0/1, it is 0/nonzero */
+#define zone_in_use(x)  (minix_bit(zone_map,(x)-FIRSTZONE+1))
+#define inode_in_use(x) (minix_bit(inode_map,(x)))
 
-#define mark_inode(x) (setbit(inode_map,(x)),changed=1)
-#define unmark_inode(x) (clrbit(inode_map,(x)),changed=1)
+#define mark_inode(x)   (minix_setbit(inode_map,(x)))
+#define unmark_inode(x) (minix_clrbit(inode_map,(x)))
 
-#define mark_zone(x) (setbit(zone_map,(x)-FIRSTZONE+1),changed=1)
-#define unmark_zone(x) (clrbit(zone_map,(x)-FIRSTZONE+1),changed=1)
+#define mark_zone(x)   (minix_setbit(zone_map,(x)-FIRSTZONE+1))
+#define unmark_zone(x) (minix_clrbit(zone_map,(x)-FIRSTZONE+1))
 
 
-static void recursive_check(unsigned int ino);
+static void recursive_check(unsigned ino);
 #if ENABLE_FEATURE_MINIX2
-static void recursive_check2(unsigned int ino);
+static void recursive_check2(unsigned ino);
 #endif
 
-static void leave(int) ATTRIBUTE_NORETURN;
-static void leave(int status)
+static void die(const char *str) ATTRIBUTE_NORETURN;
+static void die(const char *str)
 {
        if (termios_set)
                tcsetattr(0, TCSANOW, &termios);
-       exit(status);
-}
-
-static void die(const char *str)
-{
-       bb_error_msg("%s", str);
-       leave(8);
+       bb_error_msg_and_die("%s", str);
 }
 
 /* File-name data */
@@ -381,7 +396,7 @@ static int check_zone_nr(uint16_t *nr, smallint *corrected)
 /*
  * read-block reads block nr into the buffer at addr.
  */
-static void read_block(unsigned int nr, char *addr)
+static void read_block(unsigned nr, char *addr)
 {
        if (!nr) {
                memset(addr, 0, BLOCK_SIZE);
@@ -403,7 +418,7 @@ static void read_block(unsigned int nr, char *addr)
 /*
  * write_block writes block nr to disk.
  */
-static void write_block(unsigned int nr, char *addr)
+static void write_block(unsigned nr, char *addr)
 {
        if (!nr)
                return;
@@ -427,7 +442,7 @@ static void write_block(unsigned int nr, char *addr)
  * It sets 'changed' if the inode has needed changing, and re-writes
  * any indirect blocks with errors.
  */
-static int map_block(struct minix1_inode *inode, unsigned int blknr)
+static int map_block(struct minix1_inode *inode, unsigned blknr)
 {
        uint16_t ind[BLOCK_SIZE >> 1];
        uint16_t dind[BLOCK_SIZE >> 1];
@@ -463,7 +478,7 @@ static int map_block(struct minix1_inode *inode, unsigned int blknr)
 }
 
 #if ENABLE_FEATURE_MINIX2
-static int map_block2(struct minix2_inode *inode, unsigned int blknr)
+static int map_block2(struct minix2_inode *inode, unsigned blknr)
 {
        uint32_t ind[BLOCK_SIZE >> 2];
        uint32_t dind[BLOCK_SIZE >> 2];
@@ -535,7 +550,7 @@ static void write_super_block(void)
 
        if (BLOCK_SIZE != lseek(IN, BLOCK_SIZE, SEEK_SET))
                die("seek failed in write_super_block");
-       if (BLOCK_SIZE != write(IN, super_block_buffer, BLOCK_SIZE))
+       if (BLOCK_SIZE != write(IN, blockbuf->super_block_buffer, BLOCK_SIZE))
                die("cannot write super-block");
 }
 
@@ -578,7 +593,7 @@ static void read_superblock(void)
 {
        if (BLOCK_SIZE != lseek(IN, BLOCK_SIZE, SEEK_SET))
                die("seek failed");
-       if (BLOCK_SIZE != read(IN, super_block_buffer, BLOCK_SIZE))
+       if (BLOCK_SIZE != read(IN, blockbuf->super_block_buffer, BLOCK_SIZE))
                die("cannot read super block");
        /* already initialized to:
        namelen = 14;
@@ -643,7 +658,7 @@ static void read_tables(void)
        }
 }
 
-static struct minix1_inode *get_inode(unsigned int nr)
+static struct minix1_inode *get_inode(unsigned nr)
 {
        struct minix1_inode *inode;
 
@@ -653,13 +668,13 @@ static struct minix1_inode *get_inode(unsigned int nr)
        inode = Inode1 + nr;
        if (!inode_count[nr]) {
                if (!inode_in_use(nr)) {
-                       printf("Inode1 %d is marked as 'unused', but it is used "
+                       printf("Inode %d is marked as 'unused', but it is used "
                                        "for file '%s'\n", nr, current_name);
                        if (repair) {
                                if (ask("Mark as 'in use'", 1))
                                        mark_inode(nr);
-                       } else {
-                               errors_uncorrected = 1;
+                               else
+                                       errors_uncorrected = 1;
                        }
                }
                if (S_ISDIR(inode->i_mode))
@@ -689,7 +704,7 @@ static struct minix1_inode *get_inode(unsigned int nr)
 }
 
 #if ENABLE_FEATURE_MINIX2
-static struct minix2_inode *get_inode2(unsigned int nr)
+static struct minix2_inode *get_inode2(unsigned nr)
 {
        struct minix2_inode *inode;
 
@@ -699,7 +714,7 @@ static struct minix2_inode *get_inode2(unsigned int nr)
        inode = Inode2 + nr;
        if (!inode_count[nr]) {
                if (!inode_in_use(nr)) {
-                       printf("Inode1 %d is marked as 'unused', but it is used "
+                       printf("Inode %d is marked as 'unused', but it is used "
                                        "for file '%s'\n", nr, current_name);
                        if (repair) {
                                if (ask("Mark as 'in use'", 1))
@@ -818,7 +833,7 @@ static int add_zone2(uint32_t *znr, smallint *corrected)
 
 static void add_zone_ind(uint16_t *znr, smallint *corrected)
 {
-       static char blk[BLOCK_SIZE];
+#define blk (blockbuf->add_zone_ind_blk)
        int i;
        int block;
        smallint chg_blk = 0;
@@ -831,12 +846,13 @@ static void add_zone_ind(uint16_t *znr, smallint *corrected)
                add_zone(i + (uint16_t *) blk, &chg_blk);
        if (chg_blk)
                write_block(block, blk);
+#undef blk
 }
 
 #if ENABLE_FEATURE_MINIX2
 static void add_zone_ind2(uint32_t *znr, smallint *corrected)
 {
-       static char blk[BLOCK_SIZE];
+#define blk (blockbuf->add_zone_ind_blk)
        int i;
        int block;
        smallint chg_blk = 0;
@@ -849,12 +865,13 @@ static void add_zone_ind2(uint32_t *znr, smallint *corrected)
                add_zone2(i + (uint32_t *) blk, &chg_blk);
        if (chg_blk)
                write_block(block, blk);
+#undef blk
 }
 #endif
 
 static void add_zone_dind(uint16_t *znr, smallint *corrected)
 {
-       static char blk[BLOCK_SIZE];
+#define blk (blockbuf->add_zone_dind_blk)
        int i;
        int block;
        smallint chg_blk = 0;
@@ -867,12 +884,13 @@ static void add_zone_dind(uint16_t *znr, smallint *corrected)
                add_zone_ind(i + (uint16_t *) blk, &chg_blk);
        if (chg_blk)
                write_block(block, blk);
+#undef blk
 }
 
 #if ENABLE_FEATURE_MINIX2
 static void add_zone_dind2(uint32_t *znr, smallint *corrected)
 {
-       static char blk[BLOCK_SIZE];
+#define blk (blockbuf->add_zone_dind_blk)
        int i;
        int block;
        smallint chg_blk = 0;
@@ -885,11 +903,12 @@ static void add_zone_dind2(uint32_t *znr, smallint *corrected)
                add_zone_ind2(i + (uint32_t *) blk, &chg_blk);
        if (chg_blk)
                write_block(block, blk);
+#undef blk
 }
 
 static void add_zone_tind2(uint32_t *znr, smallint *corrected)
 {
-       static char blk[BLOCK_SIZE];
+#define blk (blockbuf->add_zone_tind_blk)
        int i;
        int block;
        smallint chg_blk = 0;
@@ -902,10 +921,11 @@ static void add_zone_tind2(uint32_t *znr, smallint *corrected)
                add_zone_dind2(i + (uint32_t *) blk, &chg_blk);
        if (chg_blk)
                write_block(block, blk);
+#undef blk
 }
 #endif
 
-static void check_zones(unsigned int i)
+static void check_zones(unsigned i)
 {
        struct minix1_inode *inode;
 
@@ -923,7 +943,7 @@ static void check_zones(unsigned int i)
 }
 
 #if ENABLE_FEATURE_MINIX2
-static void check_zones2(unsigned int i)
+static void check_zones2(unsigned i)
 {
        struct minix2_inode *inode;
 
@@ -943,9 +963,9 @@ static void check_zones2(unsigned int i)
 }
 #endif
 
-static void check_file(struct minix1_inode *dir, unsigned int offset)
+static void check_file(struct minix1_inode *dir, unsigned offset)
 {
-       static char blk[BLOCK_SIZE];
+#define blk (blockbuf->check_file_blk)
        struct minix1_inode *inode;
        int ino;
        char *name;
@@ -991,12 +1011,13 @@ static void check_file(struct minix1_inode *dir, unsigned int offset)
        if (inode && S_ISDIR(inode->i_mode))
                recursive_check(ino);
        pop_filename();
+#undef blk
 }
 
 #if ENABLE_FEATURE_MINIX2
-static void check_file2(struct minix2_inode *dir, unsigned int offset)
+static void check_file2(struct minix2_inode *dir, unsigned offset)
 {
-       static char blk[BLOCK_SIZE];
+#define blk (blockbuf->check_file_blk)
        struct minix2_inode *inode;
        int ino;
        char *name;
@@ -1042,13 +1063,14 @@ static void check_file2(struct minix2_inode *dir, unsigned int offset)
        if (inode && S_ISDIR(inode->i_mode))
                recursive_check2(ino);
        pop_filename();
+#undef blk
 }
 #endif
 
-static void recursive_check(unsigned int ino)
+static void recursive_check(unsigned ino)
 {
        struct minix1_inode *dir;
-       unsigned int offset;
+       unsigned offset;
 
        dir = Inode1 + ino;
        if (!S_ISDIR(dir->i_mode))
@@ -1062,10 +1084,10 @@ static void recursive_check(unsigned int ino)
 }
 
 #if ENABLE_FEATURE_MINIX2
-static void recursive_check2(unsigned int ino)
+static void recursive_check2(unsigned ino)
 {
        struct minix2_inode *dir;
-       unsigned int offset;
+       unsigned offset;
 
        dir = Inode2 + ino;
        if (!S_ISDIR(dir->i_mode))
@@ -1094,7 +1116,7 @@ static void check_counts(void)
 
        for (i = 1; i <= INODES; i++) {
                if (warn_mode && Inode1[i].i_mode && !inode_in_use(i)) {
-                       printf("Inode1 %d has non-zero mode. ", i);
+                       printf("Inode %d has non-zero mode. ", i);
                        if (ask("Clear", 1)) {
                                Inode1[i].i_mode = 0;
                                changed = 1;
@@ -1109,13 +1131,14 @@ static void check_counts(void)
                        continue;
                }
                if (!inode_in_use(i)) {
-                       printf("Inode1 %d is used, but marked as 'unused' in the bitmap. ", i);
+                       printf("Inode %d is used, but marked as 'unused' in the bitmap. ", i);
                        if (ask("Set", 1))
                                mark_inode(i);
                }
                if (Inode1[i].i_nlinks != inode_count[i]) {
-                       printf("Inode1 %d (mode=%07o), i_nlinks=%d, counted=%d. ",
-                                  i, Inode1[i].i_mode, Inode1[i].i_nlinks, inode_count[i]);
+                       printf("Inode %d (mode=%07o), i_nlinks=%d, counted=%d. ",
+                               i, Inode1[i].i_mode, Inode1[i].i_nlinks,
+                               inode_count[i]);
                        if (ask("Set i_nlinks to count", 1)) {
                                Inode1[i].i_nlinks = inode_count[i];
                                changed = 1;
@@ -1123,7 +1146,7 @@ static void check_counts(void)
                }
        }
        for (i = FIRSTZONE; i < ZONES; i++) {
-               if (zone_in_use(i) == zone_count[i])
+               if ((zone_in_use(i) != 0) == zone_count[i])
                        continue;
                if (!zone_count[i]) {
                        if (bad_zone(i))
@@ -1145,7 +1168,7 @@ static void check_counts2(void)
 
        for (i = 1; i <= INODES; i++) {
                if (warn_mode && Inode2[i].i_mode && !inode_in_use(i)) {
-                       printf("Inode1 %d has non-zero mode. ", i);
+                       printf("Inode %d has non-zero mode. ", i);
                        if (ask("Clear", 1)) {
                                Inode2[i].i_mode = 0;
                                changed = 1;
@@ -1160,14 +1183,14 @@ static void check_counts2(void)
                        continue;
                }
                if (!inode_in_use(i)) {
-                       printf("Inode1 %d is used, but marked as 'unused' in the bitmap. ", i);
+                       printf("Inode %d is used, but marked as 'unused' in the bitmap. ", i);
                        if (ask("Set", 1))
                                mark_inode(i);
                }
                if (Inode2[i].i_nlinks != inode_count[i]) {
                        printf("Inode %d (mode=%07o), i_nlinks=%d, counted=%d. ",
-                                  i, Inode2[i].i_mode, Inode2[i].i_nlinks,
-                                  inode_count[i]);
+                               i, Inode2[i].i_mode, Inode2[i].i_nlinks,
+                               inode_count[i]);
                        if (ask("Set i_nlinks to count", 1)) {
                                Inode2[i].i_nlinks = inode_count[i];
                                changed = 1;
@@ -1175,7 +1198,7 @@ static void check_counts2(void)
                }
        }
        for (i = FIRSTZONE; i < ZONES; i++) {
-               if (zone_in_use(i) == zone_count[i])
+               if ((zone_in_use(i) != 0) == zone_count[i])
                        continue;
                if (!zone_count[i]) {
                        if (bad_zone(i))
@@ -1213,12 +1236,14 @@ static void check2(void)
 void check2(void);
 #endif
 
+int fsck_minix_main(int argc, char **argv);
 int fsck_minix_main(int argc, char **argv)
 {
        struct termios tmp;
        int retcode = 0;
 
        xfunc_error_retval = 8;
+       blockbuf = xzalloc(sizeof(*blockbuf));
 
        alloc_current_name();
 #if ENABLE_FEATURE_CLEAN_UP