1/* vi: set sw=4 ts=4: */ 2/* 3 * mkfs.c - make a linux (minix) file-system. 4 * 5 * (C) 1991 Linus Torvalds. This file may be redistributed as per 6 * the Linux copyright. 7 */ 8 9/* 10 * DD.MM.YY 11 * 12 * 24.11.91 - Time began. Used the fsck sources to get started. 13 * 14 * 25.11.91 - Corrected some bugs. Added support for ".badblocks" 15 * The algorithm for ".badblocks" is a bit weird, but 16 * it should work. Oh, well. 17 * 18 * 25.01.92 - Added the -l option for getting the list of bad blocks 19 * out of a named file. (Dave Rivers, rivers@ponds.uucp) 20 * 21 * 28.02.92 - Added %-information when using -c. 22 * 23 * 28.02.93 - Added support for other namelengths than the original 24 * 14 characters so that I can test the new kernel routines.. 25 * 26 * 09.10.93 - Make exit status conform to that required by fsutil 27 * (Rik Faith, faith@cs.unc.edu) 28 * 29 * 31.10.93 - Added inode request feature, for backup floppies: use 30 * 32 inodes, for a news partition use more. 31 * (Scott Heavner, sdh@po.cwru.edu) 32 * 33 * 03.01.94 - Added support for file system valid flag. 34 * (Dr. Wettstein, greg%wind.uucp@plains.nodak.edu) 35 * 36 * 30.10.94 - added support for v2 filesystem 37 * (Andreas Schwab, schwab@issan.informatik.uni-dortmund.de) 38 * 39 * 09.11.94 - Added test to prevent overwrite of mounted fs adapted 40 * from Theodore Ts'o's (tytso@athena.mit.edu) mke2fs 41 * program. (Daniel Quinlan, quinlan@yggdrasil.com) 42 * 43 * 03.20.95 - Clear first 512 bytes of filesystem to make certain that 44 * the filesystem is not misidentified as a MS-DOS FAT filesystem. 45 * (Daniel Quinlan, quinlan@yggdrasil.com) 46 * 47 * 02.07.96 - Added small patch from Russell King to make the program a 48 * good deal more portable (janl@math.uio.no) 49 * 50 * Usage: mkfs [-c | -l filename ] [-v] [-nXX] [-iXX] device [size-in-blocks] 51 * 52 * -c for readablility checking (SLOW!) 53 * -l for getting a list of bad blocks from a file. 54 * -n for namelength (currently the kernel only uses 14 or 30) 55 * -i for number of inodes 56 * -v for v2 filesystem 57 * 58 * The device may be a block device or a image of one, but this isn't 59 * enforced (but it's not much fun on a character device :-). 60 * 61 * Modified for BusyBox by Erik Andersen <andersen@debian.org> -- 62 * removed getopt based parser and added a hand rolled one. 63 */ 64 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 <termios.h> 74#include <sys/ioctl.h> 75#include <sys/param.h> 76#include <mntent.h> 77#include "busybox.h" 78 79 80typedef unsigned char u8; 81typedef unsigned short u16; 82typedef unsigned int u32; 83 84 85#define MINIX_ROOT_INO 1 86#define MINIX_LINK_MAX 250 87#define MINIX2_LINK_MAX 65530 88 89#define MINIX_I_MAP_SLOTS 8 90#define MINIX_Z_MAP_SLOTS 64 91#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */ 92#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */ 93#define MINIX2_SUPER_MAGIC 0x2468 /* minix V2 fs */ 94#define MINIX2_SUPER_MAGIC2 0x2478 /* minix V2 fs, 30 char names */ 95#define MINIX_VALID_FS 0x0001 /* Clean fs. */ 96#define MINIX_ERROR_FS 0x0002 /* fs has errors. */ 97 98#define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode))) 99#define MINIX2_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix2_inode))) 100 101#define MINIX_V1 0x0001 /* original minix fs */ 102#define MINIX_V2 0x0002 /* minix V2 fs */ 103 104#define INODE_VERSION(inode) inode->i_sb->u.minix_sb.s_version 105 106/* 107 * This is the original minix inode layout on disk. 108 * Note the 8-bit gid and atime and ctime. 109 */ 110struct minix_inode { 111 u16 i_mode; 112 u16 i_uid; 113 u32 i_size; 114 u32 i_time; 115 u8 i_gid; 116 u8 i_nlinks; 117 u16 i_zone[9]; 118}; 119 120/* 121 * The new minix inode has all the time entries, as well as 122 * long block numbers and a third indirect block (7+1+1+1 123 * instead of 7+1+1). Also, some previously 8-bit values are 124 * now 16-bit. The inode is now 64 bytes instead of 32. 125 */ 126struct minix2_inode { 127 u16 i_mode; 128 u16 i_nlinks; 129 u16 i_uid; 130 u16 i_gid; 131 u32 i_size; 132 u32 i_atime; 133 u32 i_mtime; 134 u32 i_ctime; 135 u32 i_zone[10]; 136}; 137 138/* 139 * minix super-block data on disk 140 */ 141struct minix_super_block { 142 u16 s_ninodes; 143 u16 s_nzones; 144 u16 s_imap_blocks; 145 u16 s_zmap_blocks; 146 u16 s_firstdatazone; 147 u16 s_log_zone_size; 148 u32 s_max_size; 149 u16 s_magic; 150 u16 s_state; 151 u32 s_zones; 152}; 153 154struct minix_dir_entry { 155 u16 inode; 156 char name[0]; 157}; 158 159#define BLOCK_SIZE_BITS 10 160#define BLOCK_SIZE (1<<BLOCK_SIZE_BITS) 161 162#define NAME_MAX 255 /* # chars in a file name */ 163 164#define MINIX_INODES_PER_BLOCK ((BLOCK_SIZE)/(sizeof (struct minix_inode))) 165 166#define MINIX_VALID_FS 0x0001 /* Clean fs. */ 167#define MINIX_ERROR_FS 0x0002 /* fs has errors. */ 168 169#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */ 170#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */ 171 172#ifndef BLKGETSIZE 173#define BLKGETSIZE _IO(0x12,96) /* return device size */ 174#endif 175 176 177#ifndef __linux__ 178#define volatile 179#endif 180 181#define MINIX_ROOT_INO 1 182#define MINIX_BAD_INO 2 183 184#define TEST_BUFFER_BLOCKS 16 185#define MAX_GOOD_BLOCKS 512 186 187#define UPPER(size,n) (((size)+((n)-1))/(n)) 188#define INODE_SIZE (sizeof(struct minix_inode)) 189#ifdef BB_FEATURE_MINIX2 190#define INODE_SIZE2 (sizeof(struct minix2_inode)) 191#define INODE_BLOCKS UPPER(INODES, (version2 ? MINIX2_INODES_PER_BLOCK \ 192 : MINIX_INODES_PER_BLOCK)) 193#else 194#define INODE_BLOCKS UPPER(INODES, (MINIX_INODES_PER_BLOCK)) 195#endif 196#define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE) 197 198#define BITS_PER_BLOCK (BLOCK_SIZE<<3) 199 200static char *device_name = NULL; 201static int DEV = -1; 202static long BLOCKS = 0; 203static int check = 0; 204static int badblocks = 0; 205static int namelen = 30; /* default (changed to 30, per Linus's 206 207 suggestion, Sun Nov 21 08:05:07 1993) */ 208static int dirsize = 32; 209static int magic = MINIX_SUPER_MAGIC2; 210static int version2 = 0; 211 212static char root_block[BLOCK_SIZE] = "\0"; 213 214static char *inode_buffer = NULL; 215 216#define Inode (((struct minix_inode *) inode_buffer)-1) 217#ifdef BB_FEATURE_MINIX2 218#define Inode2 (((struct minix2_inode *) inode_buffer)-1) 219#endif 220static char super_block_buffer[BLOCK_SIZE]; 221static char boot_block_buffer[512]; 222 223#define Super (*(struct minix_super_block *)super_block_buffer) 224#define INODES ((unsigned long)Super.s_ninodes) 225#ifdef BB_FEATURE_MINIX2 226#define ZONES ((unsigned long)(version2 ? Super.s_zones : Super.s_nzones)) 227#else 228#define ZONES ((unsigned long)(Super.s_nzones)) 229#endif 230#define IMAPS ((unsigned long)Super.s_imap_blocks) 231#define ZMAPS ((unsigned long)Super.s_zmap_blocks) 232#define FIRSTZONE ((unsigned long)Super.s_firstdatazone) 233#define ZONESIZE ((unsigned long)Super.s_log_zone_size) 234#define MAXSIZE ((unsigned long)Super.s_max_size) 235#define MAGIC (Super.s_magic) 236#define NORM_FIRSTZONE (2+IMAPS+ZMAPS+INODE_BLOCKS) 237 238static char *inode_map; 239static char *zone_map; 240 241static unsigned short good_blocks_table[MAX_GOOD_BLOCKS]; 242static int used_good_blocks = 0; 243static unsigned long req_nr_inodes = 0; 244 245static inline int bit(char * a,unsigned int i) 246{ 247 return (a[i >> 3] & (1<<(i & 7))) != 0; 248} 249#define inode_in_use(x) (bit(inode_map,(x))) 250#define zone_in_use(x) (bit(zone_map,(x)-FIRSTZONE+1)) 251 252#define mark_inode(x) (setbit(inode_map,(x))) 253#define unmark_inode(x) (clrbit(inode_map,(x))) 254 255#define mark_zone(x) (setbit(zone_map,(x)-FIRSTZONE+1)) 256#define unmark_zone(x) (clrbit(zone_map,(x)-FIRSTZONE+1)) 257 258/* 259 * Check to make certain that our new filesystem won't be created on 260 * an already mounted partition. Code adapted from mke2fs, Copyright 261 * (C) 1994 Theodore Ts'o. Also licensed under GPL. 262 */ 263static void check_mount(void) 264{ 265 FILE *f; 266 struct mntent *mnt; 267 268 if ((f = setmntent(MOUNTED, "r")) == NULL) 269 return; 270 while ((mnt = getmntent(f)) != NULL) 271 if (strcmp(device_name, mnt->mnt_fsname) == 0) 272 break; 273 endmntent(f); 274 if (!mnt) 275 return; 276 277 error_msg_and_die("%s is mounted; will not make a filesystem here!", device_name); 278} 279 280static long valid_offset(int fd, int offset) 281{ 282 char ch; 283 284 if (lseek(fd, offset, 0) < 0) 285 return 0; 286 if (read(fd, &ch, 1) < 1) 287 return 0; 288 return 1; 289} 290 291static int count_blocks(int fd) 292{ 293 int high, low; 294 295 low = 0; 296 for (high = 1; valid_offset(fd, high); high *= 2) 297 low = high; 298 while (low < high - 1) { 299 const int mid = (low + high) / 2; 300 301 if (valid_offset(fd, mid)) 302 low = mid; 303 else 304 high = mid; 305 } 306 valid_offset(fd, 0); 307 return (low + 1); 308} 309 310static int get_size(const char *file) 311{ 312 int fd; 313 long size; 314 315 if ((fd = open(file, O_RDWR)) < 0) 316 perror_msg_and_die("%s", file); 317 if (ioctl(fd, BLKGETSIZE, &size) >= 0) { 318 close(fd); 319 return (size * 512); 320 } 321 322 size = count_blocks(fd); 323 close(fd); 324 return size; 325} 326 327static void write_tables(void) 328{ 329 /* Mark the super block valid. */ 330 Super.s_state |= MINIX_VALID_FS; 331 Super.s_state &= ~MINIX_ERROR_FS; 332 333 if (lseek(DEV, 0, SEEK_SET)) 334 error_msg_and_die("seek to boot block failed in write_tables"); 335 if (512 != write(DEV, boot_block_buffer, 512)) 336 error_msg_and_die("unable to clear boot sector"); 337 if (BLOCK_SIZE != lseek(DEV, BLOCK_SIZE, SEEK_SET)) 338 error_msg_and_die("seek failed in write_tables"); 339 if (BLOCK_SIZE != write(DEV, super_block_buffer, BLOCK_SIZE)) 340 error_msg_and_die("unable to write super-block"); 341 if (IMAPS * BLOCK_SIZE != write(DEV, inode_map, IMAPS * BLOCK_SIZE)) 342 error_msg_and_die("unable to write inode map"); 343 if (ZMAPS * BLOCK_SIZE != write(DEV, zone_map, ZMAPS * BLOCK_SIZE)) 344 error_msg_and_die("unable to write zone map"); 345 if (INODE_BUFFER_SIZE != write(DEV, inode_buffer, INODE_BUFFER_SIZE)) 346 error_msg_and_die("unable to write inodes"); 347 348} 349 350static void write_block(int blk, char *buffer) 351{ 352 if (blk * BLOCK_SIZE != lseek(DEV, blk * BLOCK_SIZE, SEEK_SET)) 353 error_msg_and_die("seek failed in write_block"); 354 if (BLOCK_SIZE != write(DEV, buffer, BLOCK_SIZE)) 355 error_msg_and_die("write failed in write_block"); 356} 357 358static int get_free_block(void) 359{ 360 int blk; 361 362 if (used_good_blocks + 1 >= MAX_GOOD_BLOCKS) 363 error_msg_and_die("too many bad blocks"); 364 if (used_good_blocks) 365 blk = good_blocks_table[used_good_blocks - 1] + 1; 366 else 367 blk = FIRSTZONE; 368 while (blk < ZONES && zone_in_use(blk)) 369 blk++; 370 if (blk >= ZONES) 371 error_msg_and_die("not enough good blocks"); 372 good_blocks_table[used_good_blocks] = blk; 373 used_good_blocks++; 374 return blk; 375} 376 377static void mark_good_blocks(void) 378{ 379 int blk; 380 381 for (blk = 0; blk < used_good_blocks; blk++) 382 mark_zone(good_blocks_table[blk]); 383} 384 385static int next(int zone) 386{ 387 if (!zone) 388 zone = FIRSTZONE - 1; 389 while (++zone < ZONES) 390 if (zone_in_use(zone)) 391 return zone; 392 return 0; 393} 394 395static void make_bad_inode(void) 396{ 397 struct minix_inode *inode = &Inode[MINIX_BAD_INO]; 398 int i, j, zone; 399 int ind = 0, dind = 0; 400 unsigned short ind_block[BLOCK_SIZE >> 1]; 401 unsigned short dind_block[BLOCK_SIZE >> 1]; 402 403#define NEXT_BAD (zone = next(zone)) 404 405 if (!badblocks) 406 return; 407 mark_inode(MINIX_BAD_INO); 408 inode->i_nlinks = 1; 409 inode->i_time = time(NULL); 410 inode->i_mode = S_IFREG + 0000; 411 inode->i_size = badblocks * BLOCK_SIZE; 412 zone = next(0); 413 for (i = 0; i < 7; i++) { 414 inode->i_zone[i] = zone; 415 if (!NEXT_BAD) 416 goto end_bad; 417 } 418 inode->i_zone[7] = ind = get_free_block(); 419 memset(ind_block, 0, BLOCK_SIZE); 420 for (i = 0; i < 512; i++) { 421 ind_block[i] = zone; 422 if (!NEXT_BAD) 423 goto end_bad; 424 } 425 inode->i_zone[8] = dind = get_free_block(); 426 memset(dind_block, 0, BLOCK_SIZE); 427 for (i = 0; i < 512; i++) { 428 write_block(ind, (char *) ind_block); 429 dind_block[i] = ind = get_free_block(); 430 memset(ind_block, 0, BLOCK_SIZE); 431 for (j = 0; j < 512; j++) { 432 ind_block[j] = zone; 433 if (!NEXT_BAD) 434 goto end_bad; 435 } 436 } 437 error_msg_and_die("too many bad blocks"); 438 end_bad: 439 if (ind) 440 write_block(ind, (char *) ind_block); 441 if (dind) 442 write_block(dind, (char *) dind_block); 443} 444 445#ifdef BB_FEATURE_MINIX2 446static void make_bad_inode2(void) 447{ 448 struct minix2_inode *inode = &Inode2[MINIX_BAD_INO]; 449 int i, j, zone; 450 int ind = 0, dind = 0; 451 unsigned long ind_block[BLOCK_SIZE >> 2]; 452 unsigned long dind_block[BLOCK_SIZE >> 2]; 453 454 if (!badblocks) 455 return; 456 mark_inode(MINIX_BAD_INO); 457 inode->i_nlinks = 1; 458 inode->i_atime = inode->i_mtime = inode->i_ctime = time(NULL); 459 inode->i_mode = S_IFREG + 0000; 460 inode->i_size = badblocks * BLOCK_SIZE; 461 zone = next(0); 462 for (i = 0; i < 7; i++) { 463 inode->i_zone[i] = zone; 464 if (!NEXT_BAD) 465 goto end_bad; 466 } 467 inode->i_zone[7] = ind = get_free_block(); 468 memset(ind_block, 0, BLOCK_SIZE); 469 for (i = 0; i < 256; i++) { 470 ind_block[i] = zone; 471 if (!NEXT_BAD) 472 goto end_bad; 473 } 474 inode->i_zone[8] = dind = get_free_block(); 475 memset(dind_block, 0, BLOCK_SIZE); 476 for (i = 0; i < 256; i++) { 477 write_block(ind, (char *) ind_block); 478 dind_block[i] = ind = get_free_block(); 479 memset(ind_block, 0, BLOCK_SIZE); 480 for (j = 0; j < 256; j++) { 481 ind_block[j] = zone; 482 if (!NEXT_BAD) 483 goto end_bad; 484 } 485 } 486 /* Could make triple indirect block here */ 487 error_msg_and_die("too many bad blocks"); 488 end_bad: 489 if (ind) 490 write_block(ind, (char *) ind_block); 491 if (dind) 492 write_block(dind, (char *) dind_block); 493} 494#endif 495 496static void make_root_inode(void) 497{ 498 struct minix_inode *inode = &Inode[MINIX_ROOT_INO]; 499 500 mark_inode(MINIX_ROOT_INO); 501 inode->i_zone[0] = get_free_block(); 502 inode->i_nlinks = 2; 503 inode->i_time = time(NULL); 504 if (badblocks) 505 inode->i_size = 3 * dirsize; 506 else { 507 root_block[2 * dirsize] = '\0'; 508 root_block[2 * dirsize + 1] = '\0'; 509 inode->i_size = 2 * dirsize; 510 } 511 inode->i_mode = S_IFDIR + 0755; 512 inode->i_uid = getuid(); 513 if (inode->i_uid) 514 inode->i_gid = getgid(); 515 write_block(inode->i_zone[0], root_block); 516} 517 518#ifdef BB_FEATURE_MINIX2 519static void make_root_inode2(void) 520{ 521 struct minix2_inode *inode = &Inode2[MINIX_ROOT_INO]; 522 523 mark_inode(MINIX_ROOT_INO); 524 inode->i_zone[0] = get_free_block(); 525 inode->i_nlinks = 2; 526 inode->i_atime = inode->i_mtime = inode->i_ctime = time(NULL); 527 if (badblocks) 528 inode->i_size = 3 * dirsize; 529 else { 530 root_block[2 * dirsize] = '\0'; 531 root_block[2 * dirsize + 1] = '\0'; 532 inode->i_size = 2 * dirsize; 533 } 534 inode->i_mode = S_IFDIR + 0755; 535 inode->i_uid = getuid(); 536 if (inode->i_uid) 537 inode->i_gid = getgid(); 538 write_block(inode->i_zone[0], root_block); 539} 540#endif 541 542static void setup_tables(void) 543{ 544 int i; 545 unsigned long inodes; 546 547 memset(super_block_buffer, 0, BLOCK_SIZE); 548 memset(boot_block_buffer, 0, 512); 549 MAGIC = magic; 550 ZONESIZE = 0; 551 MAXSIZE = version2 ? 0x7fffffff : (7 + 512 + 512 * 512) * 1024; 552 ZONES = BLOCKS; 553/* some magic nrs: 1 inode / 3 blocks */ 554 if (req_nr_inodes == 0) 555 inodes = BLOCKS / 3; 556 else 557 inodes = req_nr_inodes; 558 /* Round up inode count to fill block size */ 559#ifdef BB_FEATURE_MINIX2 560 if (version2) 561 inodes = ((inodes + MINIX2_INODES_PER_BLOCK - 1) & 562 ~(MINIX2_INODES_PER_BLOCK - 1)); 563 else 564#endif 565 inodes = ((inodes + MINIX_INODES_PER_BLOCK - 1) & 566 ~(MINIX_INODES_PER_BLOCK - 1)); 567 if (inodes > 65535) 568 inodes = 65535; 569 INODES = inodes; 570 IMAPS = UPPER(INODES + 1, BITS_PER_BLOCK); 571 ZMAPS = 0; 572 i = 0; 573 while (ZMAPS != 574 UPPER(BLOCKS - (2 + IMAPS + ZMAPS + INODE_BLOCKS) + 1, 575 BITS_PER_BLOCK) && i < 1000) { 576 ZMAPS = 577 UPPER(BLOCKS - (2 + IMAPS + ZMAPS + INODE_BLOCKS) + 1, 578 BITS_PER_BLOCK); 579 i++; 580 } 581 /* Real bad hack but overwise mkfs.minix can be thrown 582 * in infinite loop... 583 * try: 584 * dd if=/dev/zero of=test.fs count=10 bs=1024 585 * /sbin/mkfs.minix -i 200 test.fs 586 * */ 587 if (i >= 999) { 588 error_msg_and_die("unable to allocate buffers for maps"); 589 } 590 FIRSTZONE = NORM_FIRSTZONE; 591 inode_map = xmalloc(IMAPS * BLOCK_SIZE); 592 zone_map = xmalloc(ZMAPS * BLOCK_SIZE); 593 memset(inode_map, 0xff, IMAPS * BLOCK_SIZE); 594 memset(zone_map, 0xff, ZMAPS * BLOCK_SIZE); 595 for (i = FIRSTZONE; i < ZONES; i++) 596 unmark_zone(i); 597 for (i = MINIX_ROOT_INO; i <= INODES; i++) 598 unmark_inode(i); 599 inode_buffer = xmalloc(INODE_BUFFER_SIZE); 600 memset(inode_buffer, 0, INODE_BUFFER_SIZE); 601 printf("%ld inodes\n", INODES); 602 printf("%ld blocks\n", ZONES); 603 printf("Firstdatazone=%ld (%ld)\n", FIRSTZONE, NORM_FIRSTZONE); 604 printf("Zonesize=%d\n", BLOCK_SIZE << ZONESIZE); 605 printf("Maxsize=%ld\n\n", MAXSIZE); 606} 607 608/* 609 * Perform a test of a block; return the number of 610 * blocks readable/writeable. 611 */ 612static long do_check(char *buffer, int try, unsigned int current_block) 613{ 614 long got; 615 616 /* Seek to the correct loc. */ 617 if (lseek(DEV, current_block * BLOCK_SIZE, SEEK_SET) != 618 current_block * BLOCK_SIZE) { 619 error_msg_and_die("seek failed during testing of blocks"); 620 } 621 622 623 /* Try the read */ 624 got = read(DEV, buffer, try * BLOCK_SIZE); 625 if (got < 0) 626 got = 0; 627 if (got & (BLOCK_SIZE - 1)) { 628 printf("Weird values in do_check: probably bugs\n"); 629 } 630 got /= BLOCK_SIZE; 631 return got; 632} 633 634static unsigned int currently_testing = 0; 635 636static void alarm_intr(int alnum) 637{ 638 if (currently_testing >= ZONES) 639 return; 640 signal(SIGALRM, alarm_intr); 641 alarm(5); 642 if (!currently_testing) 643 return; 644 printf("%d ...", currently_testing); 645 fflush(stdout); 646} 647 648static void check_blocks(void) 649{ 650 int try, got; 651 static char buffer[BLOCK_SIZE * TEST_BUFFER_BLOCKS]; 652 653 currently_testing = 0; 654 signal(SIGALRM, alarm_intr); 655 alarm(5); 656 while (currently_testing < ZONES) { 657 if (lseek(DEV, currently_testing * BLOCK_SIZE, SEEK_SET) != 658 currently_testing * BLOCK_SIZE) 659 error_msg_and_die("seek failed in check_blocks"); 660 try = TEST_BUFFER_BLOCKS; 661 if (currently_testing + try > ZONES) 662 try = ZONES - currently_testing; 663 got = do_check(buffer, try, currently_testing); 664 currently_testing += got; 665 if (got == try) 666 continue; 667 if (currently_testing < FIRSTZONE) 668 error_msg_and_die("bad blocks before data-area: cannot make fs"); 669 mark_zone(currently_testing); 670 badblocks++; 671 currently_testing++; 672 } 673 if (badblocks > 1) 674 printf("%d bad blocks\n", badblocks); 675 else if (badblocks == 1) 676 printf("one bad block\n"); 677} 678 679static void get_list_blocks(filename) 680char *filename; 681 682{ 683 FILE *listfile; 684 unsigned long blockno; 685 686 listfile = xfopen(filename, "r"); 687 while (!feof(listfile)) { 688 fscanf(listfile, "%ld\n", &blockno); 689 mark_zone(blockno); 690 badblocks++; 691 } 692 if (badblocks > 1) 693 printf("%d bad blocks\n", badblocks); 694 else if (badblocks == 1) 695 printf("one bad block\n"); 696} 697 698extern int mkfs_minix_main(int argc, char **argv) 699{ 700 int i=1; 701 char *tmp; 702 struct stat statbuf; 703 char *listfile = NULL; 704 int stopIt=FALSE; 705 706 if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE) 707 error_msg_and_die("bad inode size"); 708#ifdef BB_FEATURE_MINIX2 709 if (INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE) 710 error_msg_and_die("bad inode size"); 711#endif 712 713 /* Parse options */ 714 argv++; 715 while (--argc >= 0 && *argv && **argv) { 716 if (**argv == '-') { 717 stopIt=FALSE; 718 while (i > 0 && *++(*argv) && stopIt==FALSE) { 719 switch (**argv) { 720 case 'c': 721 check = 1; 722 break; 723 case 'i': 724 { 725 char *cp=NULL; 726 if (*(*argv+1) != 0) { 727 cp = ++(*argv); 728 } else { 729 if (--argc == 0) { 730 goto goodbye; 731 } 732 cp = *(++argv); 733 } 734 req_nr_inodes = strtoul(cp, &tmp, 0); 735 if (*tmp) 736 show_usage(); 737 stopIt=TRUE; 738 break; 739 } 740 case 'l': 741 if (--argc == 0) { 742 goto goodbye; 743 } 744 listfile = *(++argv); 745 break; 746 case 'n': 747 { 748 char *cp=NULL; 749 750 if (*(*argv+1) != 0) { 751 cp = ++(*argv); 752 } else { 753 if (--argc == 0) { 754 goto goodbye; 755 } 756 cp = *(++argv); 757 } 758 i = strtoul(cp, &tmp, 0); 759 if (*tmp) 760 show_usage(); 761 if (i == 14) 762 magic = MINIX_SUPER_MAGIC; 763 else if (i == 30) 764 magic = MINIX_SUPER_MAGIC2; 765 else 766 show_usage(); 767 namelen = i; 768 dirsize = i + 2; 769 stopIt=TRUE; 770 break; 771 } 772 case 'v': 773#ifdef BB_FEATURE_MINIX2 774 version2 = 1; 775#else 776 error_msg("%s: not compiled with minix v2 support", 777 device_name); 778 exit(-1); 779#endif 780 break; 781 case '-': 782 case 'h': 783 default: 784goodbye: 785 show_usage(); 786 } 787 } 788 } else { 789 if (device_name == NULL) 790 device_name = *argv; 791 else if (BLOCKS == 0) 792 BLOCKS = strtol(*argv, &tmp, 0); 793 else { 794 goto goodbye; 795 } 796 } 797 argv++; 798 } 799 800 if (device_name && !BLOCKS) 801 BLOCKS = get_size(device_name) / 1024; 802 if (!device_name || BLOCKS < 10) { 803 show_usage(); 804 } 805#ifdef BB_FEATURE_MINIX2 806 if (version2) { 807 if (namelen == 14) 808 magic = MINIX2_SUPER_MAGIC; 809 else 810 magic = MINIX2_SUPER_MAGIC2; 811 } else 812#endif 813 if (BLOCKS > 65535) 814 BLOCKS = 65535; 815 check_mount(); /* is it already mounted? */ 816 tmp = root_block; 817 *(short *) tmp = 1; 818 strcpy(tmp + 2, "."); 819 tmp += dirsize; 820 *(short *) tmp = 1; 821 strcpy(tmp + 2, ".."); 822 tmp += dirsize; 823 *(short *) tmp = 2; 824 strcpy(tmp + 2, ".badblocks"); 825 DEV = open(device_name, O_RDWR); 826 if (DEV < 0) 827 error_msg_and_die("unable to open %s", device_name); 828 if (fstat(DEV, &statbuf) < 0) 829 error_msg_and_die("unable to stat %s", device_name); 830 if (!S_ISBLK(statbuf.st_mode)) 831 check = 0; 832 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) 833 error_msg_and_die("will not try to make filesystem on '%s'", device_name); 834 setup_tables(); 835 if (check) 836 check_blocks(); 837 else if (listfile) 838 get_list_blocks(listfile); 839#ifdef BB_FEATURE_MINIX2 840 if (version2) { 841 make_root_inode2(); 842 make_bad_inode2(); 843 } else 844#endif 845 { 846 make_root_inode(); 847 make_bad_inode(); 848 } 849 mark_good_blocks(); 850 write_tables(); 851 return( 0); 852 853} 854