2 * mkfs.minix.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 * 06.29.11 - Overall cleanups for util-linux and v3 support
50 * Davidlohr Bueso <dave@gnu.org>
52 * 06.20.15 - Do not infinite loop or crash on large devices
53 * Joshua Hudson <joshudson@gmail.com>
71 #include "minix_programs.h"
73 #include "pathnames.h"
75 #include "exitcodes.h"
78 #include "closestream.h"
79 #include "ismounted.h"
82 #define MINIX_ROOT_INO 1
83 #define MINIX_BAD_INO 2
85 #define TEST_BUFFER_BLOCKS 16
86 #define MAX_GOOD_BLOCKS 512
88 #define MINIX_MAX_INODES 65535
90 #define DEFAULT_FS_VERSION 1
93 * Global variables used in minix_programs.h inline functions
95 int fs_version
= DEFAULT_FS_VERSION
;
96 char *super_block_buffer
;
98 static char *inode_buffer
= NULL
;
100 #define Inode (((struct minix_inode *) inode_buffer) - 1)
101 #define Inode2 (((struct minix2_inode *) inode_buffer) - 1)
104 char *device_name
; /* device on a Minix file system is created */
105 int device_fd
; /* open file descriptor of the device */
106 unsigned long long fs_blocks
; /* device block count for the file system */
107 int fs_used_blocks
; /* used blocks on a device */
108 int fs_bad_blocks
; /* number of bad blocks found from device */
109 uint16_t fs_namelen
; /* maximum length of filenames */
110 size_t fs_dirsize
; /* maximum size of directory */
111 unsigned long fs_inodes
; /* number of inodes */
112 int fs_magic
; /* file system magic number */
114 check_blocks
:1; /* check for bad blocks */
117 static char root_block
[MINIX_BLOCK_SIZE
];
118 static char boot_block_buffer
[512];
119 static unsigned short good_blocks_table
[MAX_GOOD_BLOCKS
];
121 static char *inode_map
;
122 static char *zone_map
;
124 #define zone_in_use(x) (isset(zone_map,(x)-get_first_zone()+1) != 0)
126 #define mark_inode(x) (setbit(inode_map,(x)))
127 #define unmark_inode(x) (clrbit(inode_map,(x)))
129 #define mark_zone(x) (setbit(zone_map,(x)-get_first_zone()+1))
130 #define unmark_zone(x) (clrbit(zone_map,(x)-get_first_zone()+1))
132 static void __attribute__((__noreturn__
)) usage(FILE *out
)
134 fputs(USAGE_HEADER
, out
);
135 fprintf(out
, _(" %s [options] /dev/name [blocks]\n"), program_invocation_short_name
);
136 fputs(USAGE_OPTIONS
, out
);
137 fputs(_(" -1 use Minix version 1\n"), out
);
138 fputs(_(" -2, -v use Minix version 2\n"), out
);
139 fputs(_(" -3 use Minix version 3\n"), out
);
140 fputs(_(" -n, --namelength <num> maximum length of filenames\n"), out
);
141 fputs(_(" -i, --inodes <num> number of inodes for the filesystem\n"), out
);
142 fputs(_(" -c, --check check the device for bad blocks\n"), out
);
143 fputs(_(" -l, --badblocks <file> list of bad blocks from file\n"), out
);
144 fputs(USAGE_SEPARATOR
, out
);
145 fputs(USAGE_HELP
, out
);
146 fputs(USAGE_VERSION
, out
);
147 fprintf(out
, USAGE_MAN_TAIL("mkfs.minix(8)"));
148 exit(out
== stderr
? MKFS_EX_USAGE
: MKFS_EX_OK
);
152 static inline time_t mkfs_minix_time(time_t *t
)
154 const char *str
= getenv("MKFS_MINIX_TEST_SECOND_SINCE_EPOCH");
157 if (str
&& sscanf(str
, "%ld", &sec
) == 1)
161 #else /* !TEST_SCRIPT */
162 # define mkfs_minix_time(x) time(x)
165 static void super_set_state(void)
167 switch (fs_version
) {
170 Super
.s_state
|= MINIX_VALID_FS
;
171 Super
.s_state
&= ~MINIX_ERROR_FS
;
178 static void write_tables(const struct fs_control
*ctl
) {
179 unsigned long imaps
= get_nimaps();
180 unsigned long zmaps
= get_nzmaps();
181 size_t buffsz
= get_inode_buffer_size();
183 /* Mark the super block valid. */
186 if (lseek(ctl
->device_fd
, 0, SEEK_SET
))
187 err(MKFS_EX_ERROR
, _("%s: seek to boot block failed "
188 " in write_tables"), ctl
->device_name
);
189 if (write_all(ctl
->device_fd
, boot_block_buffer
, 512))
190 err(MKFS_EX_ERROR
, _("%s: unable to clear boot sector"), ctl
->device_name
);
191 if (MINIX_BLOCK_SIZE
!= lseek(ctl
->device_fd
, MINIX_BLOCK_SIZE
, SEEK_SET
))
192 err(MKFS_EX_ERROR
, _("%s: seek failed in write_tables"), ctl
->device_name
);
194 if (write_all(ctl
->device_fd
, super_block_buffer
, MINIX_BLOCK_SIZE
))
195 err(MKFS_EX_ERROR
, _("%s: unable to write super-block"), ctl
->device_name
);
197 if (write_all(ctl
->device_fd
, inode_map
, imaps
* MINIX_BLOCK_SIZE
))
198 err(MKFS_EX_ERROR
, _("%s: unable to write inode map"), ctl
->device_name
);
200 if (write_all(ctl
->device_fd
, zone_map
, zmaps
* MINIX_BLOCK_SIZE
))
201 err(MKFS_EX_ERROR
, _("%s: unable to write zone map"), ctl
->device_name
);
203 if (write_all(ctl
->device_fd
, inode_buffer
, buffsz
))
204 err(MKFS_EX_ERROR
, _("%s: unable to write inodes"), ctl
->device_name
);
207 static void write_block(const struct fs_control
*ctl
, int blk
, char * buffer
) {
208 if (blk
* MINIX_BLOCK_SIZE
!= lseek(ctl
->device_fd
, blk
* MINIX_BLOCK_SIZE
, SEEK_SET
))
209 errx(MKFS_EX_ERROR
, _("%s: seek failed in write_block"), ctl
->device_name
);
211 if (write_all(ctl
->device_fd
, buffer
, MINIX_BLOCK_SIZE
))
212 errx(MKFS_EX_ERROR
, _("%s: write failed in write_block"), ctl
->device_name
);
215 static int get_free_block(struct fs_control
*ctl
) {
217 unsigned int zones
= get_nzones();
218 unsigned int first_zone
= get_first_zone();
220 if (ctl
->fs_used_blocks
+ 1 >= MAX_GOOD_BLOCKS
)
221 errx(MKFS_EX_ERROR
, _("%s: too many bad blocks"), ctl
->device_name
);
222 if (ctl
->fs_used_blocks
)
223 blk
= good_blocks_table
[ctl
->fs_used_blocks
- 1] + 1;
226 while (blk
< zones
&& zone_in_use(blk
))
229 errx(MKFS_EX_ERROR
, _("%s: not enough good blocks"), ctl
->device_name
);
230 good_blocks_table
[ctl
->fs_used_blocks
] = blk
;
231 ctl
->fs_used_blocks
++;
235 static void mark_good_blocks(const struct fs_control
*ctl
) {
238 for (blk
=0 ; blk
< ctl
->fs_used_blocks
; blk
++)
239 mark_zone(good_blocks_table
[blk
]);
242 static inline int next(unsigned long zone
) {
243 unsigned long zones
= get_nzones();
244 unsigned long first_zone
= get_first_zone();
248 while (++zone
< zones
)
249 if (zone_in_use(zone
))
254 static void make_bad_inode_v1(struct fs_control
*ctl
)
256 struct minix_inode
* inode
= &Inode
[MINIX_BAD_INO
];
259 unsigned short ind_block
[MINIX_BLOCK_SIZE
>>1];
260 unsigned short dind_block
[MINIX_BLOCK_SIZE
>>1];
262 #define NEXT_BAD (zone = next(zone))
264 if (!ctl
->fs_bad_blocks
)
266 mark_inode(MINIX_BAD_INO
);
268 inode
->i_time
= mkfs_minix_time(NULL
);
269 inode
->i_mode
= S_IFREG
+ 0000;
270 inode
->i_size
= ctl
->fs_bad_blocks
* MINIX_BLOCK_SIZE
;
272 for (i
=0 ; i
<7 ; i
++) {
273 inode
->i_zone
[i
] = zone
;
277 inode
->i_zone
[7] = ind
= get_free_block(ctl
);
278 memset(ind_block
,0,MINIX_BLOCK_SIZE
);
279 for (i
=0 ; i
<512 ; i
++) {
284 inode
->i_zone
[8] = dind
= get_free_block(ctl
);
285 memset(dind_block
,0,MINIX_BLOCK_SIZE
);
286 for (i
=0 ; i
<512 ; i
++) {
287 write_block(ctl
, ind
,(char *) ind_block
);
288 dind_block
[i
] = ind
= get_free_block(ctl
);
289 memset(ind_block
,0,MINIX_BLOCK_SIZE
);
290 for (j
=0 ; j
<512 ; j
++) {
296 errx(MKFS_EX_ERROR
, _("%s: too many bad blocks"), ctl
->device_name
);
299 write_block(ctl
, ind
, (char *) ind_block
);
301 write_block(ctl
, dind
, (char *) dind_block
);
304 static void make_bad_inode_v2_v3 (struct fs_control
*ctl
)
306 struct minix2_inode
*inode
= &Inode2
[MINIX_BAD_INO
];
308 int ind
= 0, dind
= 0;
309 unsigned long ind_block
[MINIX_BLOCK_SIZE
>> 2];
310 unsigned long dind_block
[MINIX_BLOCK_SIZE
>> 2];
312 if (!ctl
->fs_bad_blocks
)
314 mark_inode (MINIX_BAD_INO
);
316 inode
->i_atime
= inode
->i_mtime
= inode
->i_ctime
= mkfs_minix_time(NULL
);
317 inode
->i_mode
= S_IFREG
+ 0000;
318 inode
->i_size
= ctl
->fs_bad_blocks
* MINIX_BLOCK_SIZE
;
320 for (i
= 0; i
< 7; i
++) {
321 inode
->i_zone
[i
] = zone
;
325 inode
->i_zone
[7] = ind
= get_free_block (ctl
);
326 memset (ind_block
, 0, MINIX_BLOCK_SIZE
);
327 for (i
= 0; i
< 256; i
++) {
332 inode
->i_zone
[8] = dind
= get_free_block (ctl
);
333 memset (dind_block
, 0, MINIX_BLOCK_SIZE
);
334 for (i
= 0; i
< 256; i
++) {
335 write_block (ctl
, ind
, (char *) ind_block
);
336 dind_block
[i
] = ind
= get_free_block (ctl
);
337 memset (ind_block
, 0, MINIX_BLOCK_SIZE
);
338 for (j
= 0; j
< 256; j
++) {
344 /* Could make triple indirect block here */
345 errx(MKFS_EX_ERROR
, _("%s: too many bad blocks"), ctl
->device_name
);
348 write_block (ctl
, ind
, (char *) ind_block
);
350 write_block (ctl
, dind
, (char *) dind_block
);
353 static void make_bad_inode(struct fs_control
*ctl
)
355 if (fs_version
< 2) {
356 make_bad_inode_v1(ctl
);
359 make_bad_inode_v2_v3(ctl
);
362 static void make_root_inode_v1(struct fs_control
*ctl
) {
363 struct minix_inode
* inode
= &Inode
[MINIX_ROOT_INO
];
365 mark_inode(MINIX_ROOT_INO
);
366 inode
->i_zone
[0] = get_free_block(ctl
);
368 inode
->i_time
= mkfs_minix_time(NULL
);
369 if (ctl
->fs_bad_blocks
)
370 inode
->i_size
= 3 * ctl
->fs_dirsize
;
372 memset(&root_block
[2 * ctl
->fs_dirsize
], 0, ctl
->fs_dirsize
);
373 inode
->i_size
= 2 * ctl
->fs_dirsize
;
375 inode
->i_mode
= S_IFDIR
+ 0755;
376 inode
->i_uid
= getuid();
378 inode
->i_gid
= getgid();
379 write_block(ctl
, inode
->i_zone
[0],root_block
);
382 static void make_root_inode_v2_v3 (struct fs_control
*ctl
) {
383 struct minix2_inode
*inode
= &Inode2
[MINIX_ROOT_INO
];
385 mark_inode (MINIX_ROOT_INO
);
386 inode
->i_zone
[0] = get_free_block (ctl
);
388 inode
->i_atime
= inode
->i_mtime
= inode
->i_ctime
= mkfs_minix_time(NULL
);
390 if (ctl
->fs_bad_blocks
)
391 inode
->i_size
= 3 * ctl
->fs_dirsize
;
393 memset(&root_block
[2 * ctl
->fs_dirsize
], 0, ctl
->fs_dirsize
);
394 inode
->i_size
= 2 * ctl
->fs_dirsize
;
397 inode
->i_mode
= S_IFDIR
+ 0755;
398 inode
->i_uid
= getuid();
400 inode
->i_gid
= getgid();
401 write_block (ctl
, inode
->i_zone
[0], root_block
);
404 static void make_root_inode(struct fs_control
*ctl
)
406 char *tmp
= root_block
;
408 if (fs_version
== 3) {
409 *(uint32_t *) tmp
= 1;
410 strcpy(tmp
+ 4, ".");
411 tmp
+= ctl
->fs_dirsize
;
412 *(uint32_t *) tmp
= 1;
413 strcpy(tmp
+ 4, "..");
414 tmp
+= ctl
->fs_dirsize
;
415 *(uint32_t *) tmp
= 2;
416 strcpy(tmp
+ 4, ".badblocks");
418 *(uint16_t *) tmp
= 1;
419 strcpy(tmp
+ 2, ".");
420 tmp
+= ctl
->fs_dirsize
;
421 *(uint16_t *) tmp
= 1;
422 strcpy(tmp
+ 2, "..");
423 tmp
+= ctl
->fs_dirsize
;
424 *(uint16_t *) tmp
= 2;
425 strcpy(tmp
+ 2, ".badblocks");
427 if (fs_version
< 2) {
428 make_root_inode_v1(ctl
);
431 make_root_inode_v2_v3(ctl
);
434 static void super_set_nzones(const struct fs_control
*ctl
)
436 switch (fs_version
) {
438 Super3
.s_zones
= ctl
->fs_blocks
;
441 Super
.s_zones
= ctl
->fs_blocks
;
444 Super
.s_nzones
= ctl
->fs_blocks
;
449 static void super_init_maxsize(void)
451 switch (fs_version
) {
453 Super3
.s_max_size
= 2147483647L;
456 Super
.s_max_size
= 0x7fffffff;
459 Super
.s_max_size
= (7+512+512*512)*1024;
464 static void super_set_map_blocks(const struct fs_control
*ctl
, unsigned long inodes
)
466 switch (fs_version
) {
468 Super3
.s_imap_blocks
= UPPER(inodes
+ 1, BITS_PER_BLOCK
);
469 Super3
.s_zmap_blocks
= UPPER(ctl
->fs_blocks
- (1 + get_nimaps() + inode_blocks()),
471 Super3
.s_firstdatazone
= first_zone_data();
474 Super
.s_imap_blocks
= UPPER(inodes
+ 1, BITS_PER_BLOCK
);
475 Super
.s_zmap_blocks
= UPPER(ctl
->fs_blocks
- (1 + get_nimaps() + inode_blocks()),
477 Super
.s_firstdatazone
= first_zone_data();
482 static void super_set_magic(const struct fs_control
*ctl
)
484 switch (fs_version
) {
486 Super3
.s_magic
= ctl
->fs_magic
;
489 Super
.s_magic
= ctl
->fs_magic
;
494 static void setup_tables(const struct fs_control
*ctl
) {
495 unsigned long inodes
, zmaps
, imaps
, zones
, i
;
497 super_block_buffer
= xcalloc(1, MINIX_BLOCK_SIZE
);
499 memset(boot_block_buffer
,0,512);
500 super_set_magic(ctl
);
502 if (fs_version
== 3) {
503 Super3
.s_log_zone_size
= 0;
504 Super3
.s_blocksize
= MINIX_BLOCK_SIZE
;
507 Super
.s_log_zone_size
= 0;
510 super_init_maxsize();
511 super_set_nzones(ctl
);
512 zones
= get_nzones();
514 /* some magic nrs: 1 inode / 3 blocks for smaller filesystems,
515 * for one inode / 16 blocks for large ones. mkfs will eventually
516 * crab about too far when getting close to the maximum size. */
517 if (ctl
->fs_inodes
== 0)
518 if (2048 * 1024 < ctl
->fs_blocks
) /* 2GB */
519 inodes
= ctl
->fs_blocks
/ 16;
520 else if (512 * 1024 < ctl
->fs_blocks
) /* 0.5GB */
521 inodes
= ctl
->fs_blocks
/ 8;
523 inodes
= ctl
->fs_blocks
/ 3;
525 inodes
= ctl
->fs_inodes
;
526 /* Round up inode count to fill block size */
527 if (fs_version
== 2 || fs_version
== 3)
528 inodes
= ((inodes
+ MINIX2_INODES_PER_BLOCK
- 1) &
529 ~(MINIX2_INODES_PER_BLOCK
- 1));
531 inodes
= ((inodes
+ MINIX_INODES_PER_BLOCK
- 1) &
532 ~(MINIX_INODES_PER_BLOCK
- 1));
535 Super3
.s_ninodes
= inodes
;
537 Super
.s_ninodes
= inodes
;
538 if (inodes
> MINIX_MAX_INODES
)
539 inodes
= MINIX_MAX_INODES
;
541 super_set_map_blocks(ctl
, inodes
);
542 if (MINIX_MAX_INODES
< first_zone_data())
544 _("First data block at %jd, which is too far (max %d).\n"
545 "Try specifying fewer inodes by passing --inodes <num>"),
546 (intmax_t)first_zone_data(),
548 imaps
= get_nimaps();
549 zmaps
= get_nzmaps();
551 inode_map
= xmalloc(imaps
* MINIX_BLOCK_SIZE
);
552 zone_map
= xmalloc(zmaps
* MINIX_BLOCK_SIZE
);
553 memset(inode_map
,0xff,imaps
* MINIX_BLOCK_SIZE
);
554 memset(zone_map
,0xff,zmaps
* MINIX_BLOCK_SIZE
);
556 for (i
= get_first_zone() ; i
<zones
; i
++)
558 for (i
= MINIX_ROOT_INO
; i
<=inodes
; i
++)
561 inode_buffer
= xmalloc(get_inode_buffer_size());
562 memset(inode_buffer
,0, get_inode_buffer_size());
564 printf(P_("%lu inode\n", "%lu inodes\n", inodes
), inodes
);
565 printf(P_("%lu block\n", "%lu blocks\n", zones
), zones
);
566 printf(_("Firstdatazone=%jd (%jd)\n"),
567 (intmax_t)get_first_zone(), (intmax_t)first_zone_data());
568 printf(_("Zonesize=%zu\n"), (size_t) MINIX_BLOCK_SIZE
<< get_zone_size());
569 printf(_("Maxsize=%zu\n\n"),get_max_size());
573 * Perform a test of a block; return the number of
574 * blocks readable/writable.
576 static size_t do_check(const struct fs_control
*ctl
, char * buffer
, int try, unsigned int current_block
) {
579 /* Seek to the correct loc. */
580 if (lseek(ctl
->device_fd
, current_block
* MINIX_BLOCK_SIZE
, SEEK_SET
) !=
581 current_block
* MINIX_BLOCK_SIZE
)
582 err(MKFS_EX_ERROR
, _("%s: seek failed during testing of blocks"),
586 got
= read(ctl
->device_fd
, buffer
, try * MINIX_BLOCK_SIZE
);
587 if (got
< 0) got
= 0;
588 if (got
& (MINIX_BLOCK_SIZE
- 1 )) {
589 printf(_("Weird values in do_check: probably bugs\n"));
591 got
/= MINIX_BLOCK_SIZE
;
595 static unsigned int currently_testing
= 0;
597 static void alarm_intr(int alnum
__attribute__ ((__unused__
))) {
598 unsigned long zones
= get_nzones();
600 if (currently_testing
>= zones
)
602 signal(SIGALRM
,alarm_intr
);
604 if (!currently_testing
)
606 printf("%d ...", currently_testing
);
610 static void check_blocks(struct fs_control
*ctl
) {
612 static char buffer
[MINIX_BLOCK_SIZE
* TEST_BUFFER_BLOCKS
];
613 unsigned long zones
= get_nzones();
614 unsigned long first_zone
= get_first_zone();
617 signal(SIGALRM
,alarm_intr
);
619 while (currently_testing
< zones
) {
620 if (lseek(ctl
->device_fd
, currently_testing
* MINIX_BLOCK_SIZE
,SEEK_SET
) !=
621 currently_testing
*MINIX_BLOCK_SIZE
)
622 errx(MKFS_EX_ERROR
, _("%s: seek failed in check_blocks"),
624 try = TEST_BUFFER_BLOCKS
;
625 if (currently_testing
+ try > zones
)
626 try = zones
-currently_testing
;
627 got
= do_check(ctl
, buffer
, try, currently_testing
);
628 currently_testing
+= got
;
631 if (currently_testing
< first_zone
)
632 errx(MKFS_EX_ERROR
, _("%s: bad blocks before data-area: "
633 "cannot make fs"), ctl
->device_name
);
634 mark_zone(currently_testing
);
635 ctl
->fs_bad_blocks
++;
638 if (ctl
->fs_bad_blocks
> 0)
639 printf(P_("%d bad block\n", "%d bad blocks\n", ctl
->fs_bad_blocks
), ctl
->fs_bad_blocks
);
642 static void get_list_blocks(struct fs_control
*ctl
, char *filename
) {
644 unsigned long blockno
;
646 listfile
= fopen(filename
,"r");
647 if (listfile
== NULL
)
648 err(MKFS_EX_ERROR
, _("%s: can't open file of bad blocks"),
651 while (!feof(listfile
)) {
652 if (fscanf(listfile
,"%lu\n", &blockno
) != 1) {
653 printf(_("badblock number input error on line %d\n"), ctl
->fs_bad_blocks
+ 1);
654 errx(MKFS_EX_ERROR
, _("%s: cannot read badblocks file"),
658 ctl
->fs_bad_blocks
++;
662 if (ctl
->fs_bad_blocks
> 0)
663 printf(P_("%d bad block\n", "%d bad blocks\n", ctl
->fs_bad_blocks
), ctl
->fs_bad_blocks
);
666 static int find_super_magic(const struct fs_control
*ctl
)
668 switch (fs_version
) {
670 if (ctl
->fs_namelen
== 14)
671 return MINIX_SUPER_MAGIC
;
672 return MINIX_SUPER_MAGIC2
;
674 if (ctl
->fs_namelen
== 14)
675 return MINIX2_SUPER_MAGIC
;
676 return MINIX2_SUPER_MAGIC2
;
678 return MINIX3_SUPER_MAGIC
;
684 static void determine_device_blocks(struct fs_control
*ctl
, const struct stat
*statbuf
)
686 unsigned long long dev_blocks
;
688 if (S_ISBLK(statbuf
->st_mode
)) {
691 if (blkdev_get_sector_size(ctl
->device_fd
, §orsize
) == -1)
692 sectorsize
= DEFAULT_SECTOR_SIZE
; /* kernel < 2.3.3 */
693 if (MINIX_BLOCK_SIZE
< sectorsize
)
694 errx(MKFS_EX_ERROR
, _("block size smaller than physical "
695 "sector size of %s"), ctl
->device_name
);
696 if (blkdev_get_size(ctl
->device_fd
, &dev_blocks
) == -1)
697 errx(MKFS_EX_ERROR
, _("cannot determine size of %s"), ctl
->device_name
);
698 dev_blocks
/= MINIX_BLOCK_SIZE
;
699 } else if (!S_ISBLK(statbuf
->st_mode
))
700 dev_blocks
= statbuf
->st_size
/ MINIX_BLOCK_SIZE
;
702 ctl
->fs_blocks
= dev_blocks
;
703 else if (dev_blocks
< ctl
->fs_blocks
)
705 _("%s: requested blocks (%llu) exceeds available (%llu) blocks\n"),
706 ctl
->device_name
, ctl
->fs_blocks
, dev_blocks
);
707 if (ctl
->fs_blocks
< 10)
708 errx(MKFS_EX_ERROR
, _("%s: number of blocks too small"), ctl
->device_name
);
709 if (fs_version
== 1 && ctl
->fs_blocks
> MINIX_MAX_INODES
)
710 ctl
->fs_blocks
= MINIX_MAX_INODES
;
711 if (ctl
->fs_blocks
> (4 + ((MINIX_MAX_INODES
- 4) * BITS_PER_BLOCK
)))
712 ctl
->fs_blocks
= 4 + ((MINIX_MAX_INODES
- 4) * BITS_PER_BLOCK
); /* Utter maximum: Clip. */
715 static void check_user_instructions(struct fs_control
*ctl
)
717 switch (fs_version
) {
720 if (ctl
->fs_namelen
== 14 || ctl
->fs_namelen
== 30)
721 ctl
->fs_dirsize
= ctl
->fs_namelen
+ 2;
723 errx(MKFS_EX_ERROR
, _("unsupported name length: %d"), ctl
->fs_namelen
);
726 if (ctl
->fs_namelen
== 60)
727 ctl
->fs_dirsize
= ctl
->fs_namelen
+ 4;
729 errx(MKFS_EX_ERROR
, _("unsupported name length: %d"), ctl
->fs_namelen
);
732 errx(MKFS_EX_ERROR
, _("unsupported minix file system version: %d"), fs_version
);
734 ctl
->fs_magic
= find_super_magic(ctl
);
737 int main(int argc
, char ** argv
)
739 struct fs_control ctl
= {
740 .fs_namelen
= 30, /* keep in sync with DEFAULT_FS_VERSION */
745 char * listfile
= NULL
;
746 static const struct option longopts
[] = {
747 {"namelength", required_argument
, NULL
, 'n'},
748 {"inodes", required_argument
, NULL
, 'i'},
749 {"check", no_argument
, NULL
, 'c'},
750 {"badblocks", required_argument
, NULL
, 'l'},
751 {"version", no_argument
, NULL
, 'V'},
752 {"help", no_argument
, NULL
, 'h'},
756 setlocale(LC_ALL
, "");
757 bindtextdomain(PACKAGE
, LOCALEDIR
);
759 atexit(close_stdout
);
761 while ((i
= getopt_long(argc
, argv
, "1v23n:i:cl:Vh", longopts
, NULL
)) != -1)
766 case 'v': /* kept for backwards compatibility */
767 warnx(_("-v is ambiguous, use '-2' instead"));
777 ctl
.fs_namelen
= strtou16_or_err(optarg
,
778 _("failed to parse maximum length of filenames"));
781 ctl
.fs_inodes
= strtoul_or_err(optarg
,
782 _("failed to parse number of inodes"));
785 ctl
.check_blocks
= 1;
791 printf(UTIL_LINUX_VERSION
);
796 errtryhelp(MKFS_EX_USAGE
);
801 ctl
.device_name
= argv
[0];
806 ctl
.fs_blocks
= strtoul_or_err(argv
[0], _("failed to parse number of blocks"));
808 if (!ctl
.device_name
) {
811 check_user_instructions(&ctl
);
812 if (is_mounted(ctl
.device_name
))
813 errx(MKFS_EX_ERROR
, _("%s is mounted; will not make a filesystem here!"),
815 if (stat(ctl
.device_name
, &statbuf
) < 0)
816 err(MKFS_EX_ERROR
, _("stat of %s failed"), ctl
.device_name
);
817 ctl
.device_fd
= open_blkdev_or_file(&statbuf
, ctl
.device_name
, O_RDWR
);
818 if (ctl
.device_fd
< 0)
819 err(MKFS_EX_ERROR
, _("cannot open %s"), ctl
.device_name
);
820 determine_device_blocks(&ctl
, &statbuf
);
822 if (ctl
.check_blocks
)
825 get_list_blocks(&ctl
, listfile
);
827 make_root_inode(&ctl
);
828 make_bad_inode(&ctl
);
830 mark_good_blocks(&ctl
);
832 if (close_fd(ctl
.device_fd
) != 0)
833 err(MKFS_EX_ERROR
, _("write failed"));