Ignore:
Timestamp:
Nov 4, 2007, 3:16:40 AM (16 years ago)
Author:
Bruno Cornec
Message:

Update to busybox 1.7.2

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.5/mindi-busybox/util-linux/mkfs_minix.c

    r821 r1765  
    3434 *      (Dr. Wettstein, greg%wind.uucp@plains.nodak.edu)
    3535 *
    36  * 30.10.94 - added support for v2 filesystem
    37  *        (Andreas Schwab, schwab@issan.informatik.uni-dortmund.de)
     36 * 30.10.94  - added support for v2 filesystem
     37 *          (Andreas Schwab, schwab@issan.informatik.uni-dortmund.de)
    3838 *
    3939 * 09.11.94  -  Added test to prevent overwrite of mounted fs adapted
     
    6363 */
    6464
    65 #include <stdio.h>
    66 #include <time.h>
    67 #include <unistd.h>
    68 #include <string.h>
    69 #include <signal.h>
    70 #include <fcntl.h>
    71 #include <ctype.h>
    72 #include <stdlib.h>
    73 #include <stdint.h>
    74 #include <termios.h>
    75 #include <sys/ioctl.h>
    76 #include <sys/param.h>
     65#include "libbb.h"
    7766#include <mntent.h>
    78 #include "busybox.h"
    79 
    80 #define MINIX_ROOT_INO 1
    81 #define MINIX_LINK_MAX  250
    82 #define MINIX2_LINK_MAX 65530
    83 
    84 #define MINIX_I_MAP_SLOTS   8
    85 #define MINIX_Z_MAP_SLOTS   64
    86 #define MINIX_SUPER_MAGIC   0x137F      /* original minix fs */
    87 #define MINIX_SUPER_MAGIC2  0x138F      /* minix fs, 30 char names */
    88 #define MINIX2_SUPER_MAGIC  0x2468      /* minix V2 fs */
    89 #define MINIX2_SUPER_MAGIC2 0x2478      /* minix V2 fs, 30 char names */
    90 #define MINIX_VALID_FS      0x0001      /* Clean fs. */
    91 #define MINIX_ERROR_FS      0x0002      /* fs has errors. */
    92 
    93 #define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode)))
    94 #define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode)))
    95 
    96 #define MINIX_V1        0x0001      /* original minix fs */
    97 #define MINIX_V2        0x0002      /* minix V2 fs */
    98 
    99 #define INODE_VERSION(inode)    inode->i_sb->u.minix_sb.s_version
    100 
    101 /*
    102  * This is the original minix inode layout on disk.
    103  * Note the 8-bit gid and atime and ctime.
    104  */
    105 struct minix_inode {
    106     uint16_t i_mode;
    107     uint16_t i_uid;
    108     uint32_t i_size;
    109     uint32_t i_time;
    110     uint8_t  i_gid;
    111     uint8_t  i_nlinks;
    112     uint16_t i_zone[9];
     67
     68#include "minix.h"
     69
     70#define DEBUG 0
     71
     72/* If debugging, store the very same times/uids/gids for image consistency */
     73#if DEBUG
     74# define CUR_TIME 0
     75# define GETUID 0
     76# define GETGID 0
     77#else
     78# define CUR_TIME time(NULL)
     79# define GETUID getuid()
     80# define GETGID getgid()
     81#endif
     82
     83enum {
     84    MAX_GOOD_BLOCKS         = 512,
     85    TEST_BUFFER_BLOCKS      = 16,
    11386};
    11487
    115 /*
    116  * The new minix inode has all the time entries, as well as
    117  * long block numbers and a third indirect block (7+1+1+1
    118  * instead of 7+1+1). Also, some previously 8-bit values are
    119  * now 16-bit. The inode is now 64 bytes instead of 32.
    120  */
    121 struct minix2_inode {
    122     uint16_t i_mode;
    123     uint16_t i_nlinks;
    124     uint16_t i_uid;
    125     uint16_t i_gid;
    126     uint32_t i_size;
    127     uint32_t i_atime;
    128     uint32_t i_mtime;
    129     uint32_t i_ctime;
    130     uint32_t i_zone[10];
     88#if !ENABLE_FEATURE_MINIX2
     89enum { version2 = 0 };
     90#endif
     91
     92struct globals {
     93    int dev_fd;
     94
     95#if ENABLE_FEATURE_MINIX2
     96    smallint version2;
     97#define version2 G.version2
     98#endif
     99    char *device_name;
     100    uint32_t total_blocks;
     101    int badblocks;
     102    int namelen;
     103    int dirsize;
     104    int magic;
     105    char *inode_buffer;
     106    char *inode_map;
     107    char *zone_map;
     108    int used_good_blocks;
     109    unsigned long req_nr_inodes;
     110    unsigned currently_testing;
     111
     112
     113    char root_block[BLOCK_SIZE];
     114    char super_block_buffer[BLOCK_SIZE];
     115    char boot_block_buffer[512];
     116    unsigned short good_blocks_table[MAX_GOOD_BLOCKS];
     117    /* check_blocks(): buffer[] was the biggest static in entire bbox */
     118    char check_blocks_buffer[BLOCK_SIZE * TEST_BUFFER_BLOCKS];
    131119};
    132120
    133 /*
    134  * minix super-block data on disk
    135  */
    136 struct minix_super_block {
    137     uint16_t s_ninodes;
    138     uint16_t s_nzones;
    139     uint16_t s_imap_blocks;
    140     uint16_t s_zmap_blocks;
    141     uint16_t s_firstdatazone;
    142     uint16_t s_log_zone_size;
    143     uint32_t s_max_size;
    144     uint16_t s_magic;
    145     uint16_t s_state;
    146     uint32_t s_zones;
    147 };
    148 
    149 struct minix_dir_entry {
    150     uint16_t inode;
    151     char name[0];
    152 };
    153 
    154 #define NAME_MAX         255   /* # chars in a file name */
    155 
    156 #define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode)))
    157 
    158 #define MINIX_VALID_FS               0x0001          /* Clean fs. */
    159 #define MINIX_ERROR_FS               0x0002          /* fs has errors. */
    160 
    161 #define MINIX_SUPER_MAGIC    0x137F          /* original minix fs */
    162 #define MINIX_SUPER_MAGIC2   0x138F          /* minix fs, 30 char names */
     121#define G (*ptr_to_globals)
     122
     123static ALWAYS_INLINE unsigned div_roundup(unsigned size, unsigned n)
     124{
     125    return (size + n-1) / n;
     126}
     127
     128#define INODE_BUF1              (((struct minix1_inode*)G.inode_buffer) - 1)
     129#define INODE_BUF2              (((struct minix2_inode*)G.inode_buffer) - 1)
     130
     131#define SB                      (*(struct minix_super_block*)G.super_block_buffer)
     132
     133#define SB_INODES               (SB.s_ninodes)
     134#define SB_IMAPS                (SB.s_imap_blocks)
     135#define SB_ZMAPS                (SB.s_zmap_blocks)
     136#define SB_FIRSTZONE            (SB.s_firstdatazone)
     137#define SB_ZONE_SIZE            (SB.s_log_zone_size)
     138#define SB_MAXSIZE              (SB.s_max_size)
     139#define SB_MAGIC                (SB.s_magic)
     140
     141#if !ENABLE_FEATURE_MINIX2
     142# define SB_ZONES               (SB.s_nzones)
     143# define INODE_BLOCKS           div_roundup(SB_INODES, MINIX1_INODES_PER_BLOCK)
     144#else
     145# define SB_ZONES               (version2 ? SB.s_zones : SB.s_nzones)
     146# define INODE_BLOCKS           div_roundup(SB_INODES, \
     147                                version2 ? MINIX2_INODES_PER_BLOCK : MINIX1_INODES_PER_BLOCK)
     148#endif
     149
     150#define INODE_BUFFER_SIZE       (INODE_BLOCKS * BLOCK_SIZE)
     151#define NORM_FIRSTZONE          (2 + SB_IMAPS + SB_ZMAPS + INODE_BLOCKS)
     152
     153/* Before you ask "where they come from?": */
     154/* setbit/clrbit are supplied by sys/param.h */
     155
     156static int minix_bit(const char* a, unsigned i)
     157{
     158      return a[i >> 3] & (1<<(i & 7));
     159}
     160
     161static void minix_setbit(char *a, unsigned i)
     162{
     163    setbit(a, i);
     164}
     165static void minix_clrbit(char *a, unsigned i)
     166{
     167    clrbit(a, i);
     168}
     169
     170/* Note: do not assume 0/1, it is 0/nonzero */
     171#define zone_in_use(x)  minix_bit(G.zone_map,(x)-SB_FIRSTZONE+1)
     172/*#define inode_in_use(x) minix_bit(G.inode_map,(x))*/
     173
     174#define mark_inode(x)   minix_setbit(G.inode_map,(x))
     175#define unmark_inode(x) minix_clrbit(G.inode_map,(x))
     176#define mark_zone(x)    minix_setbit(G.zone_map,(x)-SB_FIRSTZONE+1)
     177#define unmark_zone(x)  minix_clrbit(G.zone_map,(x)-SB_FIRSTZONE+1)
    163178
    164179#ifndef BLKGETSIZE
    165 #define BLKGETSIZE _IO(0x12,96)    /* return device size */
    166 #endif
    167 
    168 
    169 #ifndef __linux__
    170 #define volatile
    171 #endif
    172 
    173 #define MINIX_ROOT_INO 1
    174 #define MINIX_BAD_INO 2
    175 
    176 #define TEST_BUFFER_BLOCKS 16
    177 #define MAX_GOOD_BLOCKS 512
    178 
    179 #define UPPER(size,n) (((size)+((n)-1))/(n))
    180 #define INODE_SIZE (sizeof(struct minix_inode))
    181 #ifdef CONFIG_FEATURE_MINIX2
    182 #define INODE_SIZE2 (sizeof(struct minix2_inode))
    183 #define INODE_BLOCKS UPPER(INODES, (version2 ? MINIX2_INODES_PER_BLOCK \
    184                     : MINIX_INODES_PER_BLOCK))
    185 #else
    186 #define INODE_BLOCKS UPPER(INODES, (MINIX_INODES_PER_BLOCK))
    187 #endif
    188 #define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE)
    189 
    190 #define BITS_PER_BLOCK (BLOCK_SIZE<<3)
    191 
    192 static char *device_name;
    193 static int DEV = -1;
    194 static uint32_t BLOCKS;
    195 static int check;
    196 static int badblocks;
    197 static int namelen = 30;        /* default (changed to 30, per Linus's
    198 
    199                                    suggestion, Sun Nov 21 08:05:07 1993) */
    200 static int dirsize = 32;
    201 static int magic = MINIX_SUPER_MAGIC2;
    202 static int version2;
    203 
    204 static char root_block[BLOCK_SIZE];
    205 
    206 static char *inode_buffer;
    207 
    208 #define Inode (((struct minix_inode *) inode_buffer)-1)
    209 #ifdef CONFIG_FEATURE_MINIX2
    210 #define Inode2 (((struct minix2_inode *) inode_buffer)-1)
    211 #endif
    212 static char super_block_buffer[BLOCK_SIZE];
    213 static char boot_block_buffer[512];
    214 
    215 #define Super (*(struct minix_super_block *)super_block_buffer)
    216 #define INODES (Super.s_ninodes)
    217 #ifdef CONFIG_FEATURE_MINIX2
    218 #define ZONES (version2 ? Super.s_zones : Super.s_nzones)
    219 #else
    220 #define ZONES (Super.s_nzones)
    221 #endif
    222 #define IMAPS (Super.s_imap_blocks)
    223 #define ZMAPS (Super.s_zmap_blocks)
    224 #define FIRSTZONE (Super.s_firstdatazone)
    225 #define ZONESIZE (Super.s_log_zone_size)
    226 #define MAXSIZE (Super.s_max_size)
    227 #define MAGIC (Super.s_magic)
    228 #define NORM_FIRSTZONE (2+IMAPS+ZMAPS+INODE_BLOCKS)
    229 
    230 static char *inode_map;
    231 static char *zone_map;
    232 
    233 static unsigned short good_blocks_table[MAX_GOOD_BLOCKS];
    234 static int used_good_blocks;
    235 static unsigned long req_nr_inodes;
    236 
    237 static inline int bit(char * a,unsigned int i)
    238 {
    239       return (a[i >> 3] & (1<<(i & 7))) != 0;
    240 }
    241 #define inode_in_use(x) (bit(inode_map,(x)))
    242 #define zone_in_use(x) (bit(zone_map,(x)-FIRSTZONE+1))
    243 
    244 #define mark_inode(x) (setbit(inode_map,(x)))
    245 #define unmark_inode(x) (clrbit(inode_map,(x)))
    246 
    247 #define mark_zone(x) (setbit(zone_map,(x)-FIRSTZONE+1))
    248 #define unmark_zone(x) (clrbit(zone_map,(x)-FIRSTZONE+1))
    249 
    250 /*
    251  * Check to make certain that our new filesystem won't be created on
    252  * an already mounted partition.  Code adapted from mke2fs, Copyright
    253  * (C) 1994 Theodore Ts'o.  Also licensed under GPL.
    254  */
    255 static inline void check_mount(void)
    256 {
    257     FILE *f;
    258     struct mntent *mnt;
    259 
    260     if ((f = setmntent(MOUNTED, "r")) == NULL)
    261         return;
    262     while ((mnt = getmntent(f)) != NULL)
    263         if (strcmp(device_name, mnt->mnt_fsname) == 0)
    264             break;
    265     endmntent(f);
    266     if (!mnt)
    267         return;
    268 
    269     bb_error_msg_and_die("%s is mounted; will not make a filesystem here!", device_name);
    270 }
     180# define BLKGETSIZE     _IO(0x12,96)    /* return device size */
     181#endif
     182
    271183
    272184static long valid_offset(int fd, int offset)
     
    274186    char ch;
    275187
    276     if (lseek(fd, offset, 0) < 0)
     188    if (lseek(fd, offset, SEEK_SET) < 0)
    277189        return 0;
    278190    if (read(fd, &ch, 1) < 1)
     
    281193}
    282194
    283 static inline int count_blocks(int fd)
     195static int count_blocks(int fd)
    284196{
    285197    int high, low;
     
    288200    for (high = 1; valid_offset(fd, high); high *= 2)
    289201        low = high;
     202
    290203    while (low < high - 1) {
    291204        const int mid = (low + high) / 2;
     
    300213}
    301214
    302 static inline int get_size(const char *file)
     215static int get_size(const char *file)
    303216{
    304217    int fd;
    305218    long size;
    306219
    307     fd = bb_xopen3(file, O_RDWR, 0);
     220    fd = xopen(file, O_RDWR);
    308221    if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
    309222        close(fd);
     
    316229}
    317230
    318 static inline void write_tables(void)
     231static void write_tables(void)
    319232{
    320233    /* Mark the super block valid. */
    321     Super.s_state |= MINIX_VALID_FS;
    322     Super.s_state &= ~MINIX_ERROR_FS;
    323 
    324     if (lseek(DEV, 0, SEEK_SET))
    325         bb_error_msg_and_die("seek to boot block failed in write_tables");
    326     if (512 != write(DEV, boot_block_buffer, 512))
    327         bb_error_msg_and_die("unable to clear boot sector");
    328     if (BLOCK_SIZE != lseek(DEV, BLOCK_SIZE, SEEK_SET))
    329         bb_error_msg_and_die("seek failed in write_tables");
    330     if (BLOCK_SIZE != write(DEV, super_block_buffer, BLOCK_SIZE))
    331         bb_error_msg_and_die("unable to write super-block");
    332     if (IMAPS * BLOCK_SIZE != write(DEV, inode_map, IMAPS * BLOCK_SIZE))
    333         bb_error_msg_and_die("unable to write inode map");
    334     if (ZMAPS * BLOCK_SIZE != write(DEV, zone_map, ZMAPS * BLOCK_SIZE))
    335         bb_error_msg_and_die("unable to write zone map");
    336     if (INODE_BUFFER_SIZE != write(DEV, inode_buffer, INODE_BUFFER_SIZE))
    337         bb_error_msg_and_die("unable to write inodes");
    338 
     234    SB.s_state |= MINIX_VALID_FS;
     235    SB.s_state &= ~MINIX_ERROR_FS;
     236
     237    msg_eol = "seek to 0 failed";
     238    xlseek(G.dev_fd, 0, SEEK_SET);
     239
     240    msg_eol = "cannot clear boot sector";
     241    xwrite(G.dev_fd, G.boot_block_buffer, 512);
     242
     243    msg_eol = "seek to BLOCK_SIZE failed";
     244    xlseek(G.dev_fd, BLOCK_SIZE, SEEK_SET);
     245
     246    msg_eol = "cannot write superblock";
     247    xwrite(G.dev_fd, G.super_block_buffer, BLOCK_SIZE);
     248
     249    msg_eol = "cannot write inode map";
     250    xwrite(G.dev_fd, G.inode_map, SB_IMAPS * BLOCK_SIZE);
     251
     252    msg_eol = "cannot write zone map";
     253    xwrite(G.dev_fd, G.zone_map, SB_ZMAPS * BLOCK_SIZE);
     254
     255    msg_eol = "cannot write inodes";
     256    xwrite(G.dev_fd, G.inode_buffer, INODE_BUFFER_SIZE);
     257
     258    msg_eol = "\n";
    339259}
    340260
    341261static void write_block(int blk, char *buffer)
    342262{
    343     if (blk * BLOCK_SIZE != lseek(DEV, blk * BLOCK_SIZE, SEEK_SET))
    344         bb_error_msg_and_die("seek failed in write_block");
    345     if (BLOCK_SIZE != write(DEV, buffer, BLOCK_SIZE))
    346         bb_error_msg_and_die("write failed in write_block");
     263    xlseek(G.dev_fd, blk * BLOCK_SIZE, SEEK_SET);
     264    xwrite(G.dev_fd, buffer, BLOCK_SIZE);
    347265}
    348266
     
    351269    int blk;
    352270
    353     if (used_good_blocks + 1 >= MAX_GOOD_BLOCKS)
     271    if (G.used_good_blocks + 1 >= MAX_GOOD_BLOCKS)
    354272        bb_error_msg_and_die("too many bad blocks");
    355     if (used_good_blocks)
    356         blk = good_blocks_table[used_good_blocks - 1] + 1;
     273    if (G.used_good_blocks)
     274        blk = G.good_blocks_table[G.used_good_blocks - 1] + 1;
    357275    else
    358         blk = FIRSTZONE;
    359     while (blk < ZONES && zone_in_use(blk))
     276        blk = SB_FIRSTZONE;
     277    while (blk < SB_ZONES && zone_in_use(blk))
    360278        blk++;
    361     if (blk >= ZONES)
     279    if (blk >= SB_ZONES)
    362280        bb_error_msg_and_die("not enough good blocks");
    363     good_blocks_table[used_good_blocks] = blk;
    364     used_good_blocks++;
     281    G.good_blocks_table[G.used_good_blocks] = blk;
     282    G.used_good_blocks++;
    365283    return blk;
    366284}
    367285
    368 static inline void mark_good_blocks(void)
     286static void mark_good_blocks(void)
    369287{
    370288    int blk;
    371289
    372     for (blk = 0; blk < used_good_blocks; blk++)
    373         mark_zone(good_blocks_table[blk]);
     290    for (blk = 0; blk < G.used_good_blocks; blk++)
     291        mark_zone(G.good_blocks_table[blk]);
    374292}
    375293
     
    377295{
    378296    if (!zone)
    379         zone = FIRSTZONE - 1;
    380     while (++zone < ZONES)
     297        zone = SB_FIRSTZONE - 1;
     298    while (++zone < SB_ZONES)
    381299        if (zone_in_use(zone))
    382300            return zone;
     
    384302}
    385303
    386 static inline void make_bad_inode(void)
    387 {
    388     struct minix_inode *inode = &Inode[MINIX_BAD_INO];
     304static void make_bad_inode(void)
     305{
     306    struct minix1_inode *inode = &INODE_BUF1[MINIX_BAD_INO];
    389307    int i, j, zone;
    390308    int ind = 0, dind = 0;
     
    394312#define NEXT_BAD (zone = next(zone))
    395313
    396     if (!badblocks)
     314    if (!G.badblocks)
    397315        return;
    398316    mark_inode(MINIX_BAD_INO);
    399317    inode->i_nlinks = 1;
    400     inode->i_time = time(NULL);
     318    /* BTW, setting this makes all images different */
     319    /* it's harder to check for bugs then - diff isn't helpful :(... */
     320    inode->i_time = CUR_TIME;
    401321    inode->i_mode = S_IFREG + 0000;
    402     inode->i_size = badblocks * BLOCK_SIZE;
     322    inode->i_size = G.badblocks * BLOCK_SIZE;
    403323    zone = next(0);
    404324    for (i = 0; i < 7; i++) {
     
    427347    }
    428348    bb_error_msg_and_die("too many bad blocks");
    429   end_bad:
     349 end_bad:
    430350    if (ind)
    431351        write_block(ind, (char *) ind_block);
     
    434354}
    435355
    436 #ifdef CONFIG_FEATURE_MINIX2
    437 static inline void make_bad_inode2(void)
    438 {
    439     struct minix2_inode *inode = &Inode2[MINIX_BAD_INO];
     356#if ENABLE_FEATURE_MINIX2
     357static void make_bad_inode2(void)
     358{
     359    struct minix2_inode *inode = &INODE_BUF2[MINIX_BAD_INO];
    440360    int i, j, zone;
    441361    int ind = 0, dind = 0;
     
    443363    unsigned long dind_block[BLOCK_SIZE >> 2];
    444364
    445     if (!badblocks)
     365    if (!G.badblocks)
    446366        return;
    447367    mark_inode(MINIX_BAD_INO);
    448368    inode->i_nlinks = 1;
    449     inode->i_atime = inode->i_mtime = inode->i_ctime = time(NULL);
     369    inode->i_atime = inode->i_mtime = inode->i_ctime = CUR_TIME;
    450370    inode->i_mode = S_IFREG + 0000;
    451     inode->i_size = badblocks * BLOCK_SIZE;
     371    inode->i_size = G.badblocks * BLOCK_SIZE;
    452372    zone = next(0);
    453373    for (i = 0; i < 7; i++) {
     
    477397    /* Could make triple indirect block here */
    478398    bb_error_msg_and_die("too many bad blocks");
    479   end_bad:
     399 end_bad:
    480400    if (ind)
    481401        write_block(ind, (char *) ind_block);
     
    483403        write_block(dind, (char *) dind_block);
    484404}
    485 #endif
    486 
    487 static inline void make_root_inode(void)
    488 {
    489     struct minix_inode *inode = &Inode[MINIX_ROOT_INO];
     405#else
     406void make_bad_inode2(void);
     407#endif
     408
     409static void make_root_inode(void)
     410{
     411    struct minix1_inode *inode = &INODE_BUF1[MINIX_ROOT_INO];
    490412
    491413    mark_inode(MINIX_ROOT_INO);
    492414    inode->i_zone[0] = get_free_block();
    493415    inode->i_nlinks = 2;
    494     inode->i_time = time(NULL);
    495     if (badblocks)
    496         inode->i_size = 3 * dirsize;
     416    inode->i_time = CUR_TIME;
     417    if (G.badblocks)
     418        inode->i_size = 3 * G.dirsize;
    497419    else {
    498         root_block[2 * dirsize] = '\0';
    499         root_block[2 * dirsize + 1] = '\0';
    500         inode->i_size = 2 * dirsize;
     420        G.root_block[2 * G.dirsize] = '\0';
     421        G.root_block[2 * G.dirsize + 1] = '\0';
     422        inode->i_size = 2 * G.dirsize;
    501423    }
    502424    inode->i_mode = S_IFDIR + 0755;
    503     inode->i_uid = getuid();
     425    inode->i_uid = GETUID;
    504426    if (inode->i_uid)
    505         inode->i_gid = getgid();
    506     write_block(inode->i_zone[0], root_block);
    507 }
    508 
    509 #ifdef CONFIG_FEATURE_MINIX2
    510 static inline void make_root_inode2(void)
    511 {
    512     struct minix2_inode *inode = &Inode2[MINIX_ROOT_INO];
     427        inode->i_gid = GETGID;
     428    write_block(inode->i_zone[0], G.root_block);
     429}
     430
     431#if ENABLE_FEATURE_MINIX2
     432static void make_root_inode2(void)
     433{
     434    struct minix2_inode *inode = &INODE_BUF2[MINIX_ROOT_INO];
    513435
    514436    mark_inode(MINIX_ROOT_INO);
    515437    inode->i_zone[0] = get_free_block();
    516438    inode->i_nlinks = 2;
    517     inode->i_atime = inode->i_mtime = inode->i_ctime = time(NULL);
    518     if (badblocks)
    519         inode->i_size = 3 * dirsize;
     439    inode->i_atime = inode->i_mtime = inode->i_ctime = CUR_TIME;
     440    if (G.badblocks)
     441        inode->i_size = 3 * G.dirsize;
    520442    else {
    521         root_block[2 * dirsize] = '\0';
    522         root_block[2 * dirsize + 1] = '\0';
    523         inode->i_size = 2 * dirsize;
     443        G.root_block[2 * G.dirsize] = '\0';
     444        G.root_block[2 * G.dirsize + 1] = '\0';
     445        inode->i_size = 2 * G.dirsize;
    524446    }
    525447    inode->i_mode = S_IFDIR + 0755;
    526     inode->i_uid = getuid();
     448    inode->i_uid = GETUID;
    527449    if (inode->i_uid)
    528         inode->i_gid = getgid();
    529     write_block(inode->i_zone[0], root_block);
    530 }
    531 #endif
    532 
    533 static inline void setup_tables(void)
    534 {
    535     int i;
     450        inode->i_gid = GETGID;
     451    write_block(inode->i_zone[0], G.root_block);
     452}
     453#else
     454void make_root_inode2(void);
     455#endif
     456
     457/*
     458 * Perform a test of a block; return the number of
     459 * blocks readable.
     460 */
     461static size_t do_check(char *buffer, size_t try, unsigned current_block)
     462{
     463    ssize_t got;
     464
     465    /* Seek to the correct loc. */
     466    msg_eol = "seek failed during testing of blocks";
     467    xlseek(G.dev_fd, current_block * BLOCK_SIZE, SEEK_SET);
     468    msg_eol = "\n";
     469
     470    /* Try the read */
     471    got = read(G.dev_fd, buffer, try * BLOCK_SIZE);
     472    if (got < 0)
     473        got = 0;
     474    try = ((size_t)got) / BLOCK_SIZE;
     475
     476    if (got & (BLOCK_SIZE - 1))
     477        fprintf(stderr, "Short read at block %u\n", (unsigned)(current_block + try));
     478    return try;
     479}
     480
     481static void alarm_intr(int alnum)
     482{
     483    if (G.currently_testing >= SB_ZONES)
     484        return;
     485    signal(SIGALRM, alarm_intr);
     486    alarm(5);
     487    if (!G.currently_testing)
     488        return;
     489    printf("%d ...", G.currently_testing);
     490    fflush(stdout);
     491}
     492
     493static void check_blocks(void)
     494{
     495    size_t try, got;
     496
     497    G.currently_testing = 0;
     498    signal(SIGALRM, alarm_intr);
     499    alarm(5);
     500    while (G.currently_testing < SB_ZONES) {
     501        msg_eol = "seek failed in check_blocks";
     502        xlseek(G.dev_fd, G.currently_testing * BLOCK_SIZE, SEEK_SET);
     503        msg_eol = "\n";
     504        try = TEST_BUFFER_BLOCKS;
     505        if (G.currently_testing + try > SB_ZONES)
     506            try = SB_ZONES - G.currently_testing;
     507        got = do_check(G.check_blocks_buffer, try, G.currently_testing);
     508        G.currently_testing += got;
     509        if (got == try)
     510            continue;
     511        if (G.currently_testing < SB_FIRSTZONE)
     512            bb_error_msg_and_die("bad blocks before data-area: cannot make fs");
     513        mark_zone(G.currently_testing);
     514        G.badblocks++;
     515        G.currently_testing++;
     516    }
     517    alarm(0);
     518    printf("%d bad block(s)\n", G.badblocks);
     519}
     520
     521static void get_list_blocks(char *filename)
     522{
     523    FILE *listfile;
     524    unsigned long blockno;
     525
     526    listfile = xfopen(filename, "r");
     527    while (!feof(listfile)) {
     528        fscanf(listfile, "%ld\n", &blockno);
     529        mark_zone(blockno);
     530        G.badblocks++;
     531    }
     532    printf("%d bad block(s)\n", G.badblocks);
     533}
     534
     535static void setup_tables(void)
     536{
    536537    unsigned long inodes;
    537 
    538     memset(super_block_buffer, 0, BLOCK_SIZE);
    539     memset(boot_block_buffer, 0, 512);
    540     MAGIC = magic;
    541     ZONESIZE = 0;
    542     MAXSIZE = version2 ? 0x7fffffff : (7 + 512 + 512 * 512) * 1024;
    543 #ifdef CONFIG_FEATURE_MINIX2
    544     if (version2) {
    545         Super.s_zones =  BLOCKS;
    546     } else
    547 #endif
    548         Super.s_nzones = BLOCKS;
    549 
    550 /* some magic nrs: 1 inode / 3 blocks */
    551     if (req_nr_inodes == 0)
    552         inodes = BLOCKS / 3;
     538    unsigned norm_firstzone;
     539    unsigned sb_zmaps;
     540    unsigned i;
     541
     542    /* memset(G.super_block_buffer, 0, BLOCK_SIZE); */
     543    /* memset(G.boot_block_buffer, 0, 512); */
     544    SB_MAGIC = G.magic;
     545    SB_ZONE_SIZE = 0;
     546    SB_MAXSIZE = version2 ? 0x7fffffff : (7 + 512 + 512 * 512) * 1024;
     547    if (version2)
     548        SB.s_zones = G.total_blocks;
    553549    else
    554         inodes = req_nr_inodes;
     550        SB.s_nzones = G.total_blocks;
     551
     552    /* some magic nrs: 1 inode / 3 blocks */
     553    if (G.req_nr_inodes == 0)
     554        inodes = G.total_blocks / 3;
     555    else
     556        inodes = G.req_nr_inodes;
    555557    /* Round up inode count to fill block size */
    556 #ifdef CONFIG_FEATURE_MINIX2
    557558    if (version2)
    558         inodes = ((inodes + MINIX2_INODES_PER_BLOCK - 1) &
    559                   ~(MINIX2_INODES_PER_BLOCK - 1));
     559        inodes = (inodes + MINIX2_INODES_PER_BLOCK - 1) &
     560                         ~(MINIX2_INODES_PER_BLOCK - 1);
    560561    else
    561 #endif
    562         inodes = ((inodes + MINIX_INODES_PER_BLOCK - 1) &
    563                   ~(MINIX_INODES_PER_BLOCK - 1));
     562        inodes = (inodes + MINIX1_INODES_PER_BLOCK - 1) &
     563                         ~(MINIX1_INODES_PER_BLOCK - 1);
    564564    if (inodes > 65535)
    565565        inodes = 65535;
    566     INODES = inodes;
    567     IMAPS = UPPER(INODES + 1, BITS_PER_BLOCK);
    568     ZMAPS = 0;
    569     i = 0;
    570     while (ZMAPS !=
    571            UPPER(BLOCKS - (2 + IMAPS + ZMAPS + INODE_BLOCKS) + 1,
    572                  BITS_PER_BLOCK) && i < 1000) {
    573         ZMAPS =
    574             UPPER(BLOCKS - (2 + IMAPS + ZMAPS + INODE_BLOCKS) + 1,
    575                   BITS_PER_BLOCK);
    576         i++;
    577     }
     566    SB_INODES = inodes;
     567    SB_IMAPS = div_roundup(SB_INODES + 1, BITS_PER_BLOCK);
     568
    578569    /* Real bad hack but overwise mkfs.minix can be thrown
    579570     * in infinite loop...
    580571     * try:
    581572     * dd if=/dev/zero of=test.fs count=10 bs=1024
    582      * /sbin/mkfs.minix -i 200 test.fs
    583      * */
    584     if (i >= 999) {
    585         bb_error_msg_and_die("unable to allocate buffers for maps");
    586     }
    587     FIRSTZONE = NORM_FIRSTZONE;
    588     inode_map = xmalloc(IMAPS * BLOCK_SIZE);
    589     zone_map = xmalloc(ZMAPS * BLOCK_SIZE);
    590     memset(inode_map, 0xff, IMAPS * BLOCK_SIZE);
    591     memset(zone_map, 0xff, ZMAPS * BLOCK_SIZE);
    592     for (i = FIRSTZONE; i < ZONES; i++)
     573     * mkfs.minix -i 200 test.fs
     574     */
     575    /* This code is not insane: NORM_FIRSTZONE is not a constant,
     576     * it is calculated from SB_INODES, SB_IMAPS and SB_ZMAPS */
     577    i = 999;
     578    SB_ZMAPS = 0;
     579    do {
     580        norm_firstzone = NORM_FIRSTZONE;
     581        sb_zmaps = div_roundup(G.total_blocks - norm_firstzone + 1, BITS_PER_BLOCK);
     582        if (SB_ZMAPS == sb_zmaps) goto got_it;
     583        SB_ZMAPS = sb_zmaps;
     584        /* new SB_ZMAPS, need to recalc NORM_FIRSTZONE */
     585    } while (--i);
     586    bb_error_msg_and_die("incompatible size/inode count, try different -i N");
     587 got_it:
     588
     589    SB_FIRSTZONE = norm_firstzone;
     590    G.inode_map = xmalloc(SB_IMAPS * BLOCK_SIZE);
     591    G.zone_map = xmalloc(SB_ZMAPS * BLOCK_SIZE);
     592    memset(G.inode_map, 0xff, SB_IMAPS * BLOCK_SIZE);
     593    memset(G.zone_map, 0xff, SB_ZMAPS * BLOCK_SIZE);
     594    for (i = SB_FIRSTZONE; i < SB_ZONES; i++)
    593595        unmark_zone(i);
    594     for (i = MINIX_ROOT_INO; i <= INODES; i++)
     596    for (i = MINIX_ROOT_INO; i <= SB_INODES; i++)
    595597        unmark_inode(i);
    596     inode_buffer = xmalloc(INODE_BUFFER_SIZE);
    597     memset(inode_buffer, 0, INODE_BUFFER_SIZE);
    598     printf("%ld inodes\n", (long)INODES);
    599     printf("%ld blocks\n", (long)ZONES);
    600     printf("Firstdatazone=%ld (%ld)\n", (long)FIRSTZONE, (long)NORM_FIRSTZONE);
    601     printf("Zonesize=%d\n", BLOCK_SIZE << ZONESIZE);
    602     printf("Maxsize=%ld\n\n", (long)MAXSIZE);
    603 }
    604 
    605 /*
    606  * Perform a test of a block; return the number of
    607  * blocks readable/writable.
    608  */
    609 static inline long do_check(char *buffer, int try, unsigned int current_block)
    610 {
    611     long got;
    612 
    613     /* Seek to the correct loc. */
    614     if (lseek(DEV, current_block * BLOCK_SIZE, SEEK_SET) !=
    615         current_block * BLOCK_SIZE) {
    616         bb_error_msg_and_die("seek failed during testing of blocks");
    617     }
    618 
    619 
    620     /* Try the read */
    621     got = read(DEV, buffer, try * BLOCK_SIZE);
    622     if (got < 0)
    623         got = 0;
    624     if (got & (BLOCK_SIZE - 1)) {
    625         printf("Weird values in do_check: probably bugs\n");
    626     }
    627     got /= BLOCK_SIZE;
    628     return got;
    629 }
    630 
    631 static unsigned int currently_testing;
    632 
    633 static void alarm_intr(int alnum)
    634 {
    635     if (currently_testing >= ZONES)
    636         return;
    637     signal(SIGALRM, alarm_intr);
    638     alarm(5);
    639     if (!currently_testing)
    640         return;
    641     printf("%d ...", currently_testing);
    642     fflush(stdout);
    643 }
    644 
    645 static void check_blocks(void)
    646 {
    647     int try, got;
    648     static char buffer[BLOCK_SIZE * TEST_BUFFER_BLOCKS];
    649 
    650     currently_testing = 0;
    651     signal(SIGALRM, alarm_intr);
    652     alarm(5);
    653     while (currently_testing < ZONES) {
    654         if (lseek(DEV, currently_testing * BLOCK_SIZE, SEEK_SET) !=
    655             currently_testing * BLOCK_SIZE)
    656             bb_error_msg_and_die("seek failed in check_blocks");
    657         try = TEST_BUFFER_BLOCKS;
    658         if (currently_testing + try > ZONES)
    659             try = ZONES - currently_testing;
    660         got = do_check(buffer, try, currently_testing);
    661         currently_testing += got;
    662         if (got == try)
    663             continue;
    664         if (currently_testing < FIRSTZONE)
    665             bb_error_msg_and_die("bad blocks before data-area: cannot make fs");
    666         mark_zone(currently_testing);
    667         badblocks++;
    668         currently_testing++;
    669     }
    670     if (badblocks > 1)
    671         printf("%d bad blocks\n", badblocks);
    672     else if (badblocks == 1)
    673         printf("one bad block\n");
    674 }
    675 
    676 static void get_list_blocks(char *filename)
    677 {
    678     FILE *listfile;
    679     unsigned long blockno;
    680 
    681     listfile = bb_xfopen(filename, "r");
    682     while (!feof(listfile)) {
    683         fscanf(listfile, "%ld\n", &blockno);
    684         mark_zone(blockno);
    685         badblocks++;
    686     }
    687     if (badblocks > 1)
    688         printf("%d bad blocks\n", badblocks);
    689     else if (badblocks == 1)
    690         printf("one bad block\n");
    691 }
    692 
     598    G.inode_buffer = xzalloc(INODE_BUFFER_SIZE);
     599    printf("%ld inodes\n", (long)SB_INODES);
     600    printf("%ld blocks\n", (long)SB_ZONES);
     601    printf("Firstdatazone=%ld (%ld)\n", (long)SB_FIRSTZONE, (long)norm_firstzone);
     602    printf("Zonesize=%d\n", BLOCK_SIZE << SB_ZONE_SIZE);
     603    printf("Maxsize=%ld\n", (long)SB_MAXSIZE);
     604}
     605
     606int mkfs_minix_main(int argc, char **argv);
    693607int mkfs_minix_main(int argc, char **argv)
    694608{
    695     int i=1;
     609    struct mntent *mp;
     610    unsigned opt;
    696611    char *tmp;
    697612    struct stat statbuf;
     613    char *str_i, *str_n;
    698614    char *listfile = NULL;
    699     int stopIt=FALSE;
    700 
    701     if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE)
     615
     616    PTR_TO_GLOBALS = xzalloc(sizeof(G));
     617/* default (changed to 30, per Linus's suggestion, Sun Nov 21 08:05:07 1993) */
     618    G.namelen = 30;
     619    G.dirsize = 32;
     620    G.magic = MINIX1_SUPER_MAGIC2;
     621
     622    if (INODE_SIZE1 * MINIX1_INODES_PER_BLOCK != BLOCK_SIZE)
    702623        bb_error_msg_and_die("bad inode size");
    703 #ifdef CONFIG_FEATURE_MINIX2
     624#if ENABLE_FEATURE_MINIX2
    704625    if (INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE)
    705626        bb_error_msg_and_die("bad inode size");
    706627#endif
    707628
    708     /* Parse options */
    709     argv++;
    710     while (--argc >= 0 && *argv && **argv) {
    711         if (**argv == '-') {
    712             stopIt=FALSE;
    713             while (i > 0 && *++(*argv) && stopIt==FALSE) {
    714                 switch (**argv) {
    715                     case 'c':
    716                         check = 1;
    717                         break;
    718                     case 'i':
    719                         {
    720                             char *cp=NULL;
    721                             if (*(*argv+1) != 0) {
    722                                 cp = ++(*argv);
    723                             } else {
    724                                 if (--argc == 0) {
    725                                     goto goodbye;
    726                                 }
    727                                 cp = *(++argv);
    728                             }
    729                             req_nr_inodes = strtoul(cp, &tmp, 0);
    730                             if (*tmp)
    731                                 bb_show_usage();
    732                             stopIt=TRUE;
    733                             break;
    734                         }
    735                     case 'l':
    736                         if (--argc == 0) {
    737                             goto goodbye;
    738                         }
    739                         listfile = *(++argv);
    740                         break;
    741                     case 'n':
    742                         {
    743                             char *cp=NULL;
    744 
    745                             if (*(*argv+1) != 0) {
    746                                 cp = ++(*argv);
    747                             } else {
    748                                 if (--argc == 0) {
    749                                     goto goodbye;
    750                                 }
    751                                 cp = *(++argv);
    752                             }
    753                             i = strtoul(cp, &tmp, 0);
    754                             if (*tmp)
    755                                 bb_show_usage();
    756                             if (i == 14)
    757                                 magic = MINIX_SUPER_MAGIC;
    758                             else if (i == 30)
    759                                 magic = MINIX_SUPER_MAGIC2;
    760                             else
    761                                 bb_show_usage();
    762                             namelen = i;
    763                             dirsize = i + 2;
    764                             stopIt=TRUE;
    765                             break;
    766                         }
    767                     case 'v':
    768 #ifdef CONFIG_FEATURE_MINIX2
    769                         version2 = 1;
     629    opt = getopt32(argv, "ci:l:n:v", &str_i, &listfile, &str_n);
     630    argv += optind;
     631    //if (opt & 1) -c
     632    if (opt & 2) G.req_nr_inodes = xatoul(str_i); // -i
     633    //if (opt & 4) -l
     634    if (opt & 8) { // -n
     635        G.namelen = xatoi_u(str_n);
     636        if (G.namelen == 14) G.magic = MINIX1_SUPER_MAGIC;
     637        else if (G.namelen == 30) G.magic = MINIX1_SUPER_MAGIC2;
     638        else bb_show_usage();
     639        G.dirsize = G.namelen + 2;
     640    }
     641    if (opt & 0x10) { // -v
     642#if ENABLE_FEATURE_MINIX2
     643        version2 = 1;
    770644#else
    771                         bb_error_msg("%s: not compiled with minix v2 support",
    772                                 device_name);
    773                         exit(-1);
    774 #endif
    775                         break;
    776                     case '-':
    777                     case 'h':
    778                     default:
    779 goodbye:
    780                         bb_show_usage();
    781                 }
    782             }
    783         } else {
    784             if (device_name == NULL)
    785                 device_name = *argv;
    786             else if (BLOCKS == 0)
    787                 BLOCKS = strtol(*argv, &tmp, 0);
    788             else {
    789                 goto goodbye;
    790             }
    791         }
    792         argv++;
    793     }
    794 
    795     if (device_name && !BLOCKS)
    796         BLOCKS = get_size(device_name) / 1024;
    797     if (!device_name || BLOCKS < 10) {
     645        bb_error_msg_and_die("not compiled with minix v2 support");
     646#endif
     647    }
     648
     649    G.device_name = *argv++;
     650    if (!G.device_name)
    798651        bb_show_usage();
    799     }
    800 #ifdef CONFIG_FEATURE_MINIX2
     652    if (*argv)
     653        G.total_blocks = xatou32(*argv);
     654    else
     655        G.total_blocks = get_size(G.device_name) / 1024;
     656
     657    if (G.total_blocks < 10)
     658        bb_error_msg_and_die("must have at least 10 blocks");
     659
    801660    if (version2) {
    802         if (namelen == 14)
    803             magic = MINIX2_SUPER_MAGIC;
    804         else
    805             magic = MINIX2_SUPER_MAGIC2;
    806     } else
    807 #endif
    808     if (BLOCKS > 65535)
    809         BLOCKS = 65535;
    810     check_mount();              /* is it already mounted? */
    811     tmp = root_block;
     661        G.magic = MINIX2_SUPER_MAGIC2;
     662        if (G.namelen == 14)
     663            G.magic = MINIX2_SUPER_MAGIC;
     664    } else if (G.total_blocks > 65535)
     665        G.total_blocks = 65535;
     666
     667    /* Check if it is mounted */
     668    mp = find_mount_point(G.device_name, NULL);
     669    if (mp && strcmp(G.device_name, mp->mnt_fsname) == 0)
     670        bb_error_msg_and_die("%s is mounted on %s; "
     671                "refusing to make a filesystem",
     672                G.device_name, mp->mnt_dir);
     673
     674    G.dev_fd = xopen(G.device_name, O_RDWR);
     675    if (fstat(G.dev_fd, &statbuf) < 0)
     676        bb_error_msg_and_die("cannot stat %s", G.device_name);
     677    if (!S_ISBLK(statbuf.st_mode))
     678        opt &= ~1; // clear -c (check)
     679
     680/* I don't know why someone has special code to prevent mkfs.minix
     681 * on IDE devices. Why IDE but not SCSI, etc?... */
     682#if 0
     683    else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
     684        /* what is this? */
     685        bb_error_msg_and_die("will not try "
     686            "to make filesystem on '%s'", G.device_name);
     687#endif
     688
     689    tmp = G.root_block;
    812690    *(short *) tmp = 1;
    813691    strcpy(tmp + 2, ".");
    814     tmp += dirsize;
     692    tmp += G.dirsize;
    815693    *(short *) tmp = 1;
    816694    strcpy(tmp + 2, "..");
    817     tmp += dirsize;
     695    tmp += G.dirsize;
    818696    *(short *) tmp = 2;
    819697    strcpy(tmp + 2, ".badblocks");
    820     DEV = bb_xopen3(device_name, O_RDWR, 0);
    821     if (fstat(DEV, &statbuf) < 0)
    822         bb_error_msg_and_die("unable to stat %s", device_name);
    823     if (!S_ISBLK(statbuf.st_mode))
    824         check = 0;
    825     else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
    826         bb_error_msg_and_die("will not try to make filesystem on '%s'", device_name);
     698
    827699    setup_tables();
    828     if (check)
     700
     701    if (opt & 1) // -c ?
    829702        check_blocks();
    830703    else if (listfile)
    831704        get_list_blocks(listfile);
    832 #ifdef CONFIG_FEATURE_MINIX2
     705
    833706    if (version2) {
    834707        make_root_inode2();
    835708        make_bad_inode2();
    836     } else
    837 #endif
    838     {
     709    } else {
    839710        make_root_inode();
    840711        make_bad_inode();
    841712    }
     713
    842714    mark_good_blocks();
    843715    write_tables();
    844716    return 0;
    845 
    846 }
     717}
Note: See TracChangeset for help on using the changeset viewer.