]>
git.ipfire.org Git - thirdparty/util-linux.git/blob - disk-utils/mkfs.minix.c
2 * mkfs.c - make a linux (minix) file-system.
4 * (C) 1991 Linus Torvalds. This file may be redistributed as per
11 * 24.11.91 - Time began. Used the fsck sources to get started.
13 * 25.11.91 - Corrected some bugs. Added support for ".badblocks"
14 * The algorithm for ".badblocks" is a bit weird, but
15 * it should work. Oh, well.
17 * 25.01.92 - Added the -l option for getting the list of bad blocks
18 * out of a named file. (Dave Rivers, rivers@ponds.uucp)
20 * 28.02.92 - Added %-information when using -c.
22 * 28.02.93 - Added support for other namelengths than the original
23 * 14 characters so that I can test the new kernel routines..
25 * 09.10.93 - Make exit status conform to that required by fsutil
26 * (Rik Faith, faith@cs.unc.edu)
28 * 31.10.93 - Added inode request feature, for backup floppies: use
29 * 32 inodes, for a news partition use more.
30 * (Scott Heavner, sdh@po.cwru.edu)
32 * 03.01.94 - Added support for file system valid flag.
33 * (Dr. Wettstein, greg%wind.uucp@plains.nodak.edu)
35 * 30.10.94 - Added support for v2 filesystem
36 * (Andreas Schwab, schwab@issan.informatik.uni-dortmund.de)
38 * 09.11.94 - Added test to prevent overwrite of mounted fs adapted
39 * from Theodore Ts'o's (tytso@athena.mit.edu) mke2fs
40 * program. (Daniel Quinlan, quinlan@yggdrasil.com)
42 * 03.20.95 - Clear first 512 bytes of filesystem to make certain that
43 * the filesystem is not misidentified as a MS-DOS FAT filesystem.
44 * (Daniel Quinlan, quinlan@yggdrasil.com)
46 * 02.07.96 - Added small patch from Russell King to make the program a
47 * good deal more portable (janl@math.uio.no)
49 * Usage: mkfs [-c | -l filename ] [-v] [-nXX] [-iXX] device [size-in-blocks]
51 * -c for readablility checking (SLOW!)
52 * -l for getting a list of bad blocks from a file.
53 * -n for namelength (currently the kernel only uses 14 or 30)
54 * -i for number of inodes
55 * -v for v2 filesystem
57 * The device may be a block device or a image of one, but this isn't
58 * enforced (but it's not much fun on a character device :-).
71 #include <sys/ioctl.h>
79 #define BLKGETSIZE _IO(0x12,96) /* return device size */
82 #ifdef MINIX2_SUPER_MAGIC2
87 #error "needs gcc for the bitop-__asm__'s"
90 #define MINIX_ROOT_INO 1
91 #define MINIX_BAD_INO 2
93 #define TEST_BUFFER_BLOCKS 16
94 #define MAX_GOOD_BLOCKS 512
96 #define UPPER(size,n) ((size+((n)-1))/(n))
97 #define INODE_SIZE (sizeof(struct minix_inode))
99 #define INODE_SIZE2 (sizeof(struct minix2_inode))
100 #define INODE_BLOCKS UPPER(INODES, (version2 ? MINIX2_INODES_PER_BLOCK \
101 : MINIX_INODES_PER_BLOCK))
103 #define INODE_BLOCKS UPPER(INODES, (MINIX_INODES_PER_BLOCK))
105 #define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE)
107 #define BITS_PER_BLOCK (BLOCK_SIZE<<3)
109 static char * program_name
= "mkfs";
110 static char * device_name
= NULL
;
112 static long BLOCKS
= 0;
113 static int check
= 0;
114 static int badblocks
= 0;
115 static int namelen
= 30; /* default (changed to 30, per Linus's
116 suggestion, Sun Nov 21 08:05:07 1993) */
117 static int dirsize
= 32;
118 static int magic
= MINIX_SUPER_MAGIC2
;
119 static int version2
= 0;
121 static char root_block
[BLOCK_SIZE
] = "\0";
123 static char * inode_buffer
= NULL
;
124 #define Inode (((struct minix_inode *) inode_buffer)-1)
126 #define Inode2 (((struct minix2_inode *) inode_buffer)-1)
128 static char super_block_buffer
[BLOCK_SIZE
];
129 static char boot_block_buffer
[512];
130 #define Super (*(struct minix_super_block *)super_block_buffer)
131 #define INODES ((unsigned long)Super.s_ninodes)
133 #define ZONES ((unsigned long)(version2 ? Super.s_zones : Super.s_nzones))
135 #define ZONES ((unsigned long)(Super.s_nzones))
137 #define IMAPS ((unsigned long)Super.s_imap_blocks)
138 #define ZMAPS ((unsigned long)Super.s_zmap_blocks)
139 #define FIRSTZONE ((unsigned long)Super.s_firstdatazone)
140 #define ZONESIZE ((unsigned long)Super.s_log_zone_size)
141 #define MAXSIZE ((unsigned long)Super.s_max_size)
142 #define MAGIC (Super.s_magic)
143 #define NORM_FIRSTZONE (2+IMAPS+ZMAPS+INODE_BLOCKS)
145 static char *inode_map
;
146 static char *zone_map
;
148 static unsigned short good_blocks_table
[MAX_GOOD_BLOCKS
];
149 static int used_good_blocks
= 0;
150 static unsigned long req_nr_inodes
= 0;
154 #define inode_in_use(x) (bit(inode_map,(x)))
155 #define zone_in_use(x) (bit(zone_map,(x)-FIRSTZONE+1))
157 #define mark_inode(x) (setbit(inode_map,(x)))
158 #define unmark_inode(x) (clrbit(inode_map,(x)))
160 #define mark_zone(x) (setbit(zone_map,(x)-FIRSTZONE+1))
161 #define unmark_zone(x) (clrbit(zone_map,(x)-FIRSTZONE+1))
164 fatal_error(const char * fmt_string
,int status
) {
165 fprintf(stderr
,fmt_string
,program_name
,device_name
);
171 fprintf(stderr
, "%s: %s\n", program_name
, str
);
177 fprintf(stderr
, "%s (%s)\n", program_name
, util_linux_version
);
179 _("Usage: %s [-c | -l filename] [-nXX] [-iXX] /dev/name [blocks]\n"),
185 * Check to make certain that our new filesystem won't be created on
186 * an already mounted partition. Code adapted from mke2fs, Copyright
187 * (C) 1994 Theodore Ts'o. Also licensed under GPL.
194 if ((f
= setmntent (MOUNTED
, "r")) == NULL
)
196 while ((mnt
= getmntent (f
)) != NULL
)
197 if (strcmp (device_name
, mnt
->mnt_fsname
) == 0)
203 die(_("%s is mounted; will not make a filesystem here!"));
207 valid_offset (int fd
, int offset
) {
210 if (lseek (fd
, offset
, 0) < 0)
212 if (read (fd
, &ch
, 1) < 1)
218 count_blocks (int fd
) {
222 for (high
= 1; valid_offset (fd
, high
); high
*= 2)
224 while (low
< high
- 1)
226 const int mid
= (low
+ high
) / 2;
228 if (valid_offset (fd
, mid
))
233 valid_offset (fd
, 0);
238 get_size(const char *file
) {
242 fd
= open(file
, O_RDWR
);
247 if (ioctl(fd
, BLKGETSIZE
, &size
) >= 0) {
252 size
= count_blocks(fd
);
259 /* Mark the super block valid. */
260 Super
.s_state
|= MINIX_VALID_FS
;
261 Super
.s_state
&= ~MINIX_ERROR_FS
;
263 if (lseek(DEV
, 0, SEEK_SET
))
264 die(_("seek to boot block failed in write_tables"));
265 if (512 != write(DEV
, boot_block_buffer
, 512))
266 die(_("unable to clear boot sector"));
267 if (BLOCK_SIZE
!= lseek(DEV
, BLOCK_SIZE
, SEEK_SET
))
268 die(_("seek failed in write_tables"));
269 if (BLOCK_SIZE
!= write(DEV
, super_block_buffer
, BLOCK_SIZE
))
270 die(_("unable to write super-block"));
271 if (IMAPS
*BLOCK_SIZE
!= write(DEV
,inode_map
,IMAPS
*BLOCK_SIZE
))
272 die(_("unable to write inode map"));
273 if (ZMAPS
*BLOCK_SIZE
!= write(DEV
,zone_map
,ZMAPS
*BLOCK_SIZE
))
274 die(_("unable to write zone map"));
275 if (INODE_BUFFER_SIZE
!= write(DEV
,inode_buffer
,INODE_BUFFER_SIZE
))
276 die(_("unable to write inodes"));
281 write_block(int blk
, char * buffer
) {
282 if (blk
*BLOCK_SIZE
!= lseek(DEV
, blk
*BLOCK_SIZE
, SEEK_SET
))
283 die(_("seek failed in write_block"));
284 if (BLOCK_SIZE
!= write(DEV
, buffer
, BLOCK_SIZE
))
285 die(_("write failed in write_block"));
289 get_free_block(void) {
292 if (used_good_blocks
+1 >= MAX_GOOD_BLOCKS
)
293 die(_("too many bad blocks"));
294 if (used_good_blocks
)
295 blk
= good_blocks_table
[used_good_blocks
-1]+1;
298 while (blk
< ZONES
&& zone_in_use(blk
))
301 die(_("not enough good blocks"));
302 good_blocks_table
[used_good_blocks
] = blk
;
308 mark_good_blocks(void) {
311 for (blk
=0 ; blk
< used_good_blocks
; blk
++)
312 mark_zone(good_blocks_table
[blk
]);
319 while (++zone
< ZONES
)
320 if (zone_in_use(zone
))
326 make_bad_inode(void) {
327 struct minix_inode
* inode
= &Inode
[MINIX_BAD_INO
];
330 unsigned short ind_block
[BLOCK_SIZE
>>1];
331 unsigned short dind_block
[BLOCK_SIZE
>>1];
333 #define NEXT_BAD (zone = next(zone))
337 mark_inode(MINIX_BAD_INO
);
339 inode
->i_time
= time(NULL
);
340 inode
->i_mode
= S_IFREG
+ 0000;
341 inode
->i_size
= badblocks
*BLOCK_SIZE
;
343 for (i
=0 ; i
<7 ; i
++) {
344 inode
->i_zone
[i
] = zone
;
348 inode
->i_zone
[7] = ind
= get_free_block();
349 memset(ind_block
,0,BLOCK_SIZE
);
350 for (i
=0 ; i
<512 ; i
++) {
355 inode
->i_zone
[8] = dind
= get_free_block();
356 memset(dind_block
,0,BLOCK_SIZE
);
357 for (i
=0 ; i
<512 ; i
++) {
358 write_block(ind
,(char *) ind_block
);
359 dind_block
[i
] = ind
= get_free_block();
360 memset(ind_block
,0,BLOCK_SIZE
);
361 for (j
=0 ; j
<512 ; j
++) {
367 die(_("too many bad blocks"));
370 write_block(ind
, (char *) ind_block
);
372 write_block(dind
, (char *) dind_block
);
377 make_bad_inode2 (void) {
378 struct minix2_inode
*inode
= &Inode2
[MINIX_BAD_INO
];
380 int ind
= 0, dind
= 0;
381 unsigned long ind_block
[BLOCK_SIZE
>> 2];
382 unsigned long dind_block
[BLOCK_SIZE
>> 2];
386 mark_inode (MINIX_BAD_INO
);
388 inode
->i_atime
= inode
->i_mtime
= inode
->i_ctime
= time (NULL
);
389 inode
->i_mode
= S_IFREG
+ 0000;
390 inode
->i_size
= badblocks
* BLOCK_SIZE
;
392 for (i
= 0; i
< 7; i
++) {
393 inode
->i_zone
[i
] = zone
;
397 inode
->i_zone
[7] = ind
= get_free_block ();
398 memset (ind_block
, 0, BLOCK_SIZE
);
399 for (i
= 0; i
< 256; i
++) {
404 inode
->i_zone
[8] = dind
= get_free_block ();
405 memset (dind_block
, 0, BLOCK_SIZE
);
406 for (i
= 0; i
< 256; i
++) {
407 write_block (ind
, (char *) ind_block
);
408 dind_block
[i
] = ind
= get_free_block ();
409 memset (ind_block
, 0, BLOCK_SIZE
);
410 for (j
= 0; j
< 256; j
++) {
416 /* Could make triple indirect block here */
417 die (_("too many bad blocks"));
420 write_block (ind
, (char *) ind_block
);
422 write_block (dind
, (char *) dind_block
);
427 make_root_inode(void) {
428 struct minix_inode
* inode
= &Inode
[MINIX_ROOT_INO
];
430 mark_inode(MINIX_ROOT_INO
);
431 inode
->i_zone
[0] = get_free_block();
433 inode
->i_time
= time(NULL
);
435 inode
->i_size
= 3*dirsize
;
437 root_block
[2*dirsize
] = '\0';
438 root_block
[2*dirsize
+1] = '\0';
439 inode
->i_size
= 2*dirsize
;
441 inode
->i_mode
= S_IFDIR
+ 0755;
442 inode
->i_uid
= getuid();
444 inode
->i_gid
= getgid();
445 write_block(inode
->i_zone
[0],root_block
);
450 make_root_inode2 (void) {
451 struct minix2_inode
*inode
= &Inode2
[MINIX_ROOT_INO
];
453 mark_inode (MINIX_ROOT_INO
);
454 inode
->i_zone
[0] = get_free_block ();
456 inode
->i_atime
= inode
->i_mtime
= inode
->i_ctime
= time (NULL
);
458 inode
->i_size
= 3 * dirsize
;
460 root_block
[2 * dirsize
] = '\0';
461 root_block
[2 * dirsize
+ 1] = '\0';
462 inode
->i_size
= 2 * dirsize
;
464 inode
->i_mode
= S_IFDIR
+ 0755;
465 inode
->i_uid
= getuid();
467 inode
->i_gid
= getgid();
468 write_block (inode
->i_zone
[0], root_block
);
475 unsigned long inodes
;
477 memset(super_block_buffer
,0,BLOCK_SIZE
);
478 memset(boot_block_buffer
,0,512);
481 MAXSIZE
= version2
? 0x7fffffff : (7+512+512*512)*1024;
484 /* some magic nrs: 1 inode / 3 blocks */
485 if ( req_nr_inodes
== 0 )
488 inodes
= req_nr_inodes
;
489 /* Round up inode count to fill block size */
492 inodes
= ((inodes
+ MINIX2_INODES_PER_BLOCK
- 1) &
493 ~(MINIX2_INODES_PER_BLOCK
- 1));
496 inodes
= ((inodes
+ MINIX_INODES_PER_BLOCK
- 1) &
497 ~(MINIX_INODES_PER_BLOCK
- 1));
501 IMAPS
= UPPER(INODES
+ 1,BITS_PER_BLOCK
);
502 ZMAPS
= UPPER(BLOCKS
- (1+IMAPS
+INODE_BLOCKS
), BITS_PER_BLOCK
+1);
505 * while (ZMAPS != UPPER(BLOCKS - NORM_FIRSTZONE + 1,BITS_PER_BLOCK))
506 * ZMAPS = UPPER(BLOCKS - NORM_FIRSTZONE + 1,BITS_PER_BLOCK);
507 * was no good, since it may loop. - aeb
509 FIRSTZONE
= NORM_FIRSTZONE
;
510 inode_map
= malloc(IMAPS
* BLOCK_SIZE
);
511 zone_map
= malloc(ZMAPS
* BLOCK_SIZE
);
512 if (!inode_map
|| !zone_map
)
513 die(_("unable to allocate buffers for maps"));
514 memset(inode_map
,0xff,IMAPS
* BLOCK_SIZE
);
515 memset(zone_map
,0xff,ZMAPS
* BLOCK_SIZE
);
516 for (i
= FIRSTZONE
; i
<ZONES
; i
++)
518 for (i
= MINIX_ROOT_INO
; i
<=INODES
; i
++)
520 inode_buffer
= malloc(INODE_BUFFER_SIZE
);
522 die(_("unable to allocate buffer for inodes"));
523 memset(inode_buffer
,0,INODE_BUFFER_SIZE
);
524 printf(_("%ld inodes\n"),INODES
);
525 printf(_("%ld blocks\n"),ZONES
);
526 printf(_("Firstdatazone=%ld (%ld)\n"),FIRSTZONE
,NORM_FIRSTZONE
);
527 printf(_("Zonesize=%d\n"),BLOCK_SIZE
<<ZONESIZE
);
528 printf(_("Maxsize=%ld\n\n"),MAXSIZE
);
532 * Perform a test of a block; return the number of
533 * blocks readable/writeable.
536 do_check(char * buffer
, int try, unsigned int current_block
) {
539 /* Seek to the correct loc. */
540 if (lseek(DEV
, current_block
* BLOCK_SIZE
, SEEK_SET
) !=
541 current_block
* BLOCK_SIZE
) {
542 die(_("seek failed during testing of blocks"));
547 got
= read(DEV
, buffer
, try * BLOCK_SIZE
);
548 if (got
< 0) got
= 0;
549 if (got
& (BLOCK_SIZE
- 1 )) {
550 printf(_("Weird values in do_check: probably bugs\n"));
556 static unsigned int currently_testing
= 0;
559 alarm_intr(int alnum
) {
560 if (currently_testing
>= ZONES
)
562 signal(SIGALRM
,alarm_intr
);
564 if (!currently_testing
)
566 printf("%d ...", currently_testing
);
573 static char buffer
[BLOCK_SIZE
* TEST_BUFFER_BLOCKS
];
576 signal(SIGALRM
,alarm_intr
);
578 while (currently_testing
< ZONES
) {
579 if (lseek(DEV
,currently_testing
*BLOCK_SIZE
,SEEK_SET
) !=
580 currently_testing
*BLOCK_SIZE
)
581 die(_("seek failed in check_blocks"));
582 try = TEST_BUFFER_BLOCKS
;
583 if (currently_testing
+ try > ZONES
)
584 try = ZONES
-currently_testing
;
585 got
= do_check(buffer
, try, currently_testing
);
586 currently_testing
+= got
;
589 if (currently_testing
< FIRSTZONE
)
590 die(_("bad blocks before data-area: cannot make fs"));
591 mark_zone(currently_testing
);
596 printf(_("%d bad blocks\n"), badblocks
);
597 else if (badblocks
== 1)
598 printf(_("one bad block\n"));
602 get_list_blocks(char *filename
) {
604 unsigned long blockno
;
606 listfile
=fopen(filename
,"r");
607 if(listfile
== (FILE *)NULL
) {
608 die(_("can't open file of bad blocks"));
610 while(!feof(listfile
)) {
611 fscanf(listfile
,"%ld\n", &blockno
);
616 printf(_("%d bad blocks\n"), badblocks
);
617 else if (badblocks
== 1)
618 printf(_("one bad block\n"));
622 main(int argc
, char ** argv
) {
626 char * listfile
= NULL
;
630 program_name
= *argv
;
631 if ((p
= strrchr(program_name
, '/')) != NULL
)
634 setlocale(LC_ALL
, "");
635 bindtextdomain(PACKAGE
, LOCALEDIR
);
639 (!strcmp(argv
[1], "-V") || !strcmp(argv
[1], "--version"))) {
640 printf(_("%s from %s\n"), program_name
, util_linux_version
);
644 if (INODE_SIZE
* MINIX_INODES_PER_BLOCK
!= BLOCK_SIZE
)
645 die(_("bad inode size"));
647 if (INODE_SIZE2
* MINIX2_INODES_PER_BLOCK
!= BLOCK_SIZE
)
648 die(_("bad inode size"));
651 while ((i
= getopt(argc
, argv
, "ci:l:n:v")) != EOF
)
656 req_nr_inodes
= (unsigned long) atol(optarg
);
659 listfile
= optarg
; break;
661 i
= strtoul(optarg
,&tmp
,0);
665 magic
= MINIX_SUPER_MAGIC
;
667 magic
= MINIX_SUPER_MAGIC2
;
677 fatal_error(_("%s: not compiled with minix v2 support\n"),-1);
685 if (argc
> 0 && !device_name
) {
686 device_name
= argv
[0];
691 BLOCKS
= strtol(argv
[0],&tmp
,0);
693 printf(_("strtol error: number of blocks not specified"));
698 if (device_name
&& !BLOCKS
)
699 BLOCKS
= get_size (device_name
) / 1024;
700 if (!device_name
|| BLOCKS
<10) {
706 magic
= MINIX2_SUPER_MAGIC
;
708 magic
= MINIX2_SUPER_MAGIC2
;
713 check_mount(); /* is it already mounted? */
722 strcpy(tmp
+2,".badblocks");
723 DEV
= open(device_name
,O_RDWR
);
725 die(_("unable to open %s"));
726 if (fstat(DEV
,&statbuf
)<0)
727 die(_("unable to stat %s"));
728 if (!S_ISBLK(statbuf
.st_mode
))
730 else if (statbuf
.st_rdev
== 0x0300 || statbuf
.st_rdev
== 0x0340)
731 die(_("will not try to make filesystem on '%s'"));
736 get_list_blocks(listfile
);