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"
81 #define XALLOC_EXIT_CODE MKFS_EX_ERROR
84 #define MINIX_ROOT_INO 1
85 #define MINIX_BAD_INO 2
87 #define TEST_BUFFER_BLOCKS 16
88 #define MAX_GOOD_BLOCKS 512
90 #define MINIX_MAX_INODES 65535
92 #define DEFAULT_FS_VERSION 1
95 * Global variables used in minix_programs.h inline functions
97 int fs_version
= DEFAULT_FS_VERSION
;
98 char *super_block_buffer
;
100 static char *inode_buffer
= NULL
;
102 #define Inode (((struct minix_inode *) inode_buffer) - 1)
103 #define Inode2 (((struct minix2_inode *) inode_buffer) - 1)
106 char *device_name
; /* device on a Minix file system is created */
107 int device_fd
; /* open file descriptor of the device */
108 char *lockmode
; /* as specified by --lock */
109 unsigned long long fs_blocks
; /* device block count for the file system */
110 int fs_used_blocks
; /* used blocks on a device */
111 int fs_bad_blocks
; /* number of bad blocks found from device */
112 uint16_t fs_namelen
; /* maximum length of filenames */
113 size_t fs_dirsize
; /* maximum size of directory */
114 unsigned long fs_inodes
; /* number of inodes */
115 int fs_magic
; /* file system magic number */
117 check_blocks
:1; /* check for bad blocks */
120 static char root_block
[MINIX_BLOCK_SIZE
];
121 static char boot_block_buffer
[512];
122 static unsigned short good_blocks_table
[MAX_GOOD_BLOCKS
];
124 static char *inode_map
;
125 static char *zone_map
;
127 #define zone_in_use(x) (isset(zone_map,(x)-get_first_zone()+1) != 0)
129 #define mark_inode(x) (setbit(inode_map,(x)))
130 #define unmark_inode(x) (clrbit(inode_map,(x)))
132 #define mark_zone(x) (setbit(zone_map,(x)-get_first_zone()+1))
133 #define unmark_zone(x) (clrbit(zone_map,(x)-get_first_zone()+1))
135 static void __attribute__((__noreturn__
)) usage(void)
138 fputs(USAGE_HEADER
, out
);
139 fprintf(out
, _(" %s [options] /dev/name [blocks]\n"), program_invocation_short_name
);
140 fputs(USAGE_OPTIONS
, out
);
141 fputs(_(" -1 use Minix version 1\n"), out
);
142 fputs(_(" -2, -v use Minix version 2\n"), out
);
143 fputs(_(" -3 use Minix version 3\n"), out
);
144 fputs(_(" -n, --namelength <num> maximum length of filenames\n"), out
);
145 fputs(_(" -i, --inodes <num> number of inodes for the filesystem\n"), out
);
146 fputs(_(" -c, --check check the device for bad blocks\n"), out
);
147 fputs(_(" -l, --badblocks <file> list of bad blocks from file\n"), out
);
149 " --lock[=<mode>] use exclusive device lock (%s, %s or %s)\n"), "yes", "no", "nonblock");
150 fputs(USAGE_SEPARATOR
, out
);
151 printf(USAGE_HELP_OPTIONS(25));
152 printf(USAGE_MAN_TAIL("mkfs.minix(8)"));
157 static inline time_t mkfs_minix_time(time_t *t
)
159 const char *str
= getenv("MKFS_MINIX_TEST_SECOND_SINCE_EPOCH");
162 if (str
&& sscanf(str
, "%ld", &sec
) == 1)
166 #else /* !TEST_SCRIPT */
167 # define mkfs_minix_time(x) time(x)
170 static void super_set_state(void)
172 switch (fs_version
) {
175 Super
.s_state
|= MINIX_VALID_FS
;
176 Super
.s_state
&= ~MINIX_ERROR_FS
;
183 static void write_tables(const struct fs_control
*ctl
) {
184 unsigned long imaps
= get_nimaps();
185 unsigned long zmaps
= get_nzmaps();
186 size_t buffsz
= get_inode_buffer_size();
188 /* Mark the super block valid. */
191 if (lseek(ctl
->device_fd
, 0, SEEK_SET
))
192 err(MKFS_EX_ERROR
, _("%s: seek to boot block failed "
193 " in write_tables"), ctl
->device_name
);
194 if (write_all(ctl
->device_fd
, boot_block_buffer
, 512))
195 err(MKFS_EX_ERROR
, _("%s: unable to clear boot sector"), ctl
->device_name
);
196 if (MINIX_BLOCK_SIZE
!= lseek(ctl
->device_fd
, MINIX_BLOCK_SIZE
, SEEK_SET
))
197 err(MKFS_EX_ERROR
, _("%s: seek failed in write_tables"), ctl
->device_name
);
199 if (write_all(ctl
->device_fd
, super_block_buffer
, MINIX_BLOCK_SIZE
))
200 err(MKFS_EX_ERROR
, _("%s: unable to write super-block"), ctl
->device_name
);
202 if (write_all(ctl
->device_fd
, inode_map
, imaps
* MINIX_BLOCK_SIZE
))
203 err(MKFS_EX_ERROR
, _("%s: unable to write inode map"), ctl
->device_name
);
205 if (write_all(ctl
->device_fd
, zone_map
, zmaps
* MINIX_BLOCK_SIZE
))
206 err(MKFS_EX_ERROR
, _("%s: unable to write zone map"), ctl
->device_name
);
208 if (write_all(ctl
->device_fd
, inode_buffer
, buffsz
))
209 err(MKFS_EX_ERROR
, _("%s: unable to write inodes"), ctl
->device_name
);
212 static void write_block(const struct fs_control
*ctl
, int blk
, char * buffer
) {
213 if (blk
* MINIX_BLOCK_SIZE
!= lseek(ctl
->device_fd
, blk
* MINIX_BLOCK_SIZE
, SEEK_SET
))
214 errx(MKFS_EX_ERROR
, _("%s: seek failed in write_block"), ctl
->device_name
);
216 if (write_all(ctl
->device_fd
, buffer
, MINIX_BLOCK_SIZE
))
217 errx(MKFS_EX_ERROR
, _("%s: write failed in write_block"), ctl
->device_name
);
220 static int get_free_block(struct fs_control
*ctl
) {
222 unsigned int zones
= get_nzones();
223 unsigned int first_zone
= get_first_zone();
225 if (ctl
->fs_used_blocks
+ 1 >= MAX_GOOD_BLOCKS
)
226 errx(MKFS_EX_ERROR
, _("%s: too many bad blocks"), ctl
->device_name
);
227 if (ctl
->fs_used_blocks
)
228 blk
= good_blocks_table
[ctl
->fs_used_blocks
- 1] + 1;
231 while (blk
< zones
&& zone_in_use(blk
))
234 errx(MKFS_EX_ERROR
, _("%s: not enough good blocks"), ctl
->device_name
);
235 good_blocks_table
[ctl
->fs_used_blocks
] = blk
;
236 ctl
->fs_used_blocks
++;
240 static void mark_good_blocks(const struct fs_control
*ctl
) {
243 for (blk
=0 ; blk
< ctl
->fs_used_blocks
; blk
++)
244 mark_zone(good_blocks_table
[blk
]);
247 static inline int next(unsigned long zone
) {
248 unsigned long zones
= get_nzones();
249 unsigned long first_zone
= get_first_zone();
253 while (++zone
< zones
)
254 if (zone_in_use(zone
))
259 static void make_bad_inode_v1(struct fs_control
*ctl
)
261 struct minix_inode
* inode
= &Inode
[MINIX_BAD_INO
];
264 unsigned short ind_block
[MINIX_BLOCK_SIZE
>>1];
265 unsigned short dind_block
[MINIX_BLOCK_SIZE
>>1];
267 #define NEXT_BAD (zone = next(zone))
269 if (!ctl
->fs_bad_blocks
)
271 mark_inode(MINIX_BAD_INO
);
273 inode
->i_time
= mkfs_minix_time(NULL
);
274 inode
->i_mode
= S_IFREG
+ 0000;
275 inode
->i_size
= ctl
->fs_bad_blocks
* MINIX_BLOCK_SIZE
;
277 for (i
=0 ; i
<7 ; i
++) {
278 inode
->i_zone
[i
] = zone
;
282 inode
->i_zone
[7] = ind
= get_free_block(ctl
);
283 memset(ind_block
,0,MINIX_BLOCK_SIZE
);
284 for (i
=0 ; i
<512 ; i
++) {
289 inode
->i_zone
[8] = dind
= get_free_block(ctl
);
290 memset(dind_block
,0,MINIX_BLOCK_SIZE
);
291 for (i
=0 ; i
<512 ; i
++) {
292 write_block(ctl
, ind
,(char *) ind_block
);
293 dind_block
[i
] = ind
= get_free_block(ctl
);
294 memset(ind_block
,0,MINIX_BLOCK_SIZE
);
295 for (j
=0 ; j
<512 ; j
++) {
301 errx(MKFS_EX_ERROR
, _("%s: too many bad blocks"), ctl
->device_name
);
304 write_block(ctl
, ind
, (char *) ind_block
);
306 write_block(ctl
, dind
, (char *) dind_block
);
309 static void make_bad_inode_v2_v3 (struct fs_control
*ctl
)
311 struct minix2_inode
*inode
= &Inode2
[MINIX_BAD_INO
];
313 int ind
= 0, dind
= 0;
314 unsigned long ind_block
[MINIX_BLOCK_SIZE
>> 2];
315 unsigned long dind_block
[MINIX_BLOCK_SIZE
>> 2];
317 if (!ctl
->fs_bad_blocks
)
319 mark_inode (MINIX_BAD_INO
);
321 inode
->i_atime
= inode
->i_mtime
= inode
->i_ctime
= mkfs_minix_time(NULL
);
322 inode
->i_mode
= S_IFREG
+ 0000;
323 inode
->i_size
= ctl
->fs_bad_blocks
* MINIX_BLOCK_SIZE
;
325 for (i
= 0; i
< 7; i
++) {
326 inode
->i_zone
[i
] = zone
;
330 inode
->i_zone
[7] = ind
= get_free_block (ctl
);
331 memset (ind_block
, 0, MINIX_BLOCK_SIZE
);
332 for (i
= 0; i
< 256; i
++) {
337 inode
->i_zone
[8] = dind
= get_free_block (ctl
);
338 memset (dind_block
, 0, MINIX_BLOCK_SIZE
);
339 for (i
= 0; i
< 256; i
++) {
340 write_block (ctl
, ind
, (char *) ind_block
);
341 dind_block
[i
] = ind
= get_free_block (ctl
);
342 memset (ind_block
, 0, MINIX_BLOCK_SIZE
);
343 for (j
= 0; j
< 256; j
++) {
349 /* Could make triple indirect block here */
350 errx(MKFS_EX_ERROR
, _("%s: too many bad blocks"), ctl
->device_name
);
353 write_block (ctl
, ind
, (char *) ind_block
);
355 write_block (ctl
, dind
, (char *) dind_block
);
358 static void make_bad_inode(struct fs_control
*ctl
)
360 if (fs_version
< 2) {
361 make_bad_inode_v1(ctl
);
364 make_bad_inode_v2_v3(ctl
);
367 static void make_root_inode_v1(struct fs_control
*ctl
) {
368 struct minix_inode
* inode
= &Inode
[MINIX_ROOT_INO
];
370 mark_inode(MINIX_ROOT_INO
);
371 inode
->i_zone
[0] = get_free_block(ctl
);
373 inode
->i_time
= mkfs_minix_time(NULL
);
374 if (ctl
->fs_bad_blocks
)
375 inode
->i_size
= 3 * ctl
->fs_dirsize
;
377 memset(&root_block
[2 * ctl
->fs_dirsize
], 0, ctl
->fs_dirsize
);
378 inode
->i_size
= 2 * ctl
->fs_dirsize
;
380 inode
->i_mode
= S_IFDIR
+ 0755;
381 inode
->i_uid
= getuid();
383 inode
->i_gid
= getgid();
384 write_block(ctl
, inode
->i_zone
[0],root_block
);
387 static void make_root_inode_v2_v3 (struct fs_control
*ctl
) {
388 struct minix2_inode
*inode
= &Inode2
[MINIX_ROOT_INO
];
390 mark_inode (MINIX_ROOT_INO
);
391 inode
->i_zone
[0] = get_free_block (ctl
);
393 inode
->i_atime
= inode
->i_mtime
= inode
->i_ctime
= mkfs_minix_time(NULL
);
395 if (ctl
->fs_bad_blocks
)
396 inode
->i_size
= 3 * ctl
->fs_dirsize
;
398 memset(&root_block
[2 * ctl
->fs_dirsize
], 0, ctl
->fs_dirsize
);
399 inode
->i_size
= 2 * ctl
->fs_dirsize
;
402 inode
->i_mode
= S_IFDIR
+ 0755;
403 inode
->i_uid
= getuid();
405 inode
->i_gid
= getgid();
406 write_block (ctl
, inode
->i_zone
[0], root_block
);
409 static void make_root_inode(struct fs_control
*ctl
)
411 char *tmp
= root_block
;
413 if (fs_version
== 3) {
414 *(uint32_t *) tmp
= 1;
415 strcpy(tmp
+ 4, ".");
416 tmp
+= ctl
->fs_dirsize
;
417 *(uint32_t *) tmp
= 1;
418 strcpy(tmp
+ 4, "..");
419 tmp
+= ctl
->fs_dirsize
;
420 *(uint32_t *) tmp
= 2;
421 strcpy(tmp
+ 4, ".badblocks");
423 *(uint16_t *) tmp
= 1;
424 strcpy(tmp
+ 2, ".");
425 tmp
+= ctl
->fs_dirsize
;
426 *(uint16_t *) tmp
= 1;
427 strcpy(tmp
+ 2, "..");
428 tmp
+= ctl
->fs_dirsize
;
429 *(uint16_t *) tmp
= 2;
430 strcpy(tmp
+ 2, ".badblocks");
432 if (fs_version
< 2) {
433 make_root_inode_v1(ctl
);
436 make_root_inode_v2_v3(ctl
);
439 static void super_set_nzones(const struct fs_control
*ctl
)
441 switch (fs_version
) {
443 Super3
.s_zones
= ctl
->fs_blocks
;
446 Super
.s_zones
= ctl
->fs_blocks
;
449 Super
.s_nzones
= ctl
->fs_blocks
;
454 static void super_init_maxsize(void)
456 switch (fs_version
) {
458 Super3
.s_max_size
= 2147483647L;
461 Super
.s_max_size
= 0x7fffffff;
464 Super
.s_max_size
= (7+512+512*512)*1024;
469 static void super_set_map_blocks(const struct fs_control
*ctl
, unsigned long inodes
)
471 switch (fs_version
) {
473 Super3
.s_imap_blocks
= UPPER(inodes
+ 1, BITS_PER_BLOCK
);
474 Super3
.s_zmap_blocks
= UPPER(ctl
->fs_blocks
- (1 + get_nimaps() + inode_blocks()),
476 Super3
.s_firstdatazone
= first_zone_data();
479 Super
.s_imap_blocks
= UPPER(inodes
+ 1, BITS_PER_BLOCK
);
480 Super
.s_zmap_blocks
= UPPER(ctl
->fs_blocks
- (1 + get_nimaps() + inode_blocks()),
482 Super
.s_firstdatazone
= first_zone_data();
487 static void super_set_magic(const struct fs_control
*ctl
)
489 switch (fs_version
) {
491 Super3
.s_magic
= ctl
->fs_magic
;
494 Super
.s_magic
= ctl
->fs_magic
;
499 static void setup_tables(const struct fs_control
*ctl
) {
500 unsigned long inodes
, zmaps
, imaps
, zones
, i
;
502 super_block_buffer
= xcalloc(1, MINIX_BLOCK_SIZE
);
504 memset(boot_block_buffer
,0,512);
505 super_set_magic(ctl
);
507 if (fs_version
== 3) {
508 Super3
.s_log_zone_size
= 0;
509 Super3
.s_blocksize
= MINIX_BLOCK_SIZE
;
512 Super
.s_log_zone_size
= 0;
515 super_init_maxsize();
516 super_set_nzones(ctl
);
517 zones
= get_nzones();
519 /* some magic nrs: 1 inode / 3 blocks for smaller filesystems,
520 * for one inode / 16 blocks for large ones. mkfs will eventually
521 * crab about too far when getting close to the maximum size. */
522 if (ctl
->fs_inodes
== 0)
523 if (2048 * 1024 < ctl
->fs_blocks
) /* 2GB */
524 inodes
= ctl
->fs_blocks
/ 16;
525 else if (512 * 1024 < ctl
->fs_blocks
) /* 0.5GB */
526 inodes
= ctl
->fs_blocks
/ 8;
528 inodes
= ctl
->fs_blocks
/ 3;
530 inodes
= ctl
->fs_inodes
;
531 /* Round up inode count to fill block size */
532 if (fs_version
== 2 || fs_version
== 3)
533 inodes
= ((inodes
+ MINIX2_INODES_PER_BLOCK
- 1) &
534 ~(MINIX2_INODES_PER_BLOCK
- 1));
536 inodes
= ((inodes
+ MINIX_INODES_PER_BLOCK
- 1) &
537 ~(MINIX_INODES_PER_BLOCK
- 1));
540 Super3
.s_ninodes
= inodes
;
542 if (inodes
> MINIX_MAX_INODES
)
543 inodes
= MINIX_MAX_INODES
;
544 Super
.s_ninodes
= inodes
;
546 super_set_map_blocks(ctl
, inodes
);
547 if (MINIX_MAX_INODES
< first_zone_data())
549 _("First data block at %jd, which is too far (max %d).\n"
550 "Try specifying fewer inodes by passing --inodes <num>"),
551 (intmax_t)first_zone_data(),
553 imaps
= get_nimaps();
554 zmaps
= get_nzmaps();
556 inode_map
= xmalloc(imaps
* MINIX_BLOCK_SIZE
);
557 zone_map
= xmalloc(zmaps
* MINIX_BLOCK_SIZE
);
558 memset(inode_map
,0xff,imaps
* MINIX_BLOCK_SIZE
);
559 memset(zone_map
,0xff,zmaps
* MINIX_BLOCK_SIZE
);
561 for (i
= get_first_zone() ; i
<zones
; i
++)
563 for (i
= MINIX_ROOT_INO
; i
<=inodes
; i
++)
566 inode_buffer
= xmalloc(get_inode_buffer_size());
567 memset(inode_buffer
,0, get_inode_buffer_size());
569 printf(P_("%lu inode\n", "%lu inodes\n", inodes
), inodes
);
570 printf(P_("%lu block\n", "%lu blocks\n", zones
), zones
);
571 printf(_("Firstdatazone=%jd (%jd)\n"),
572 (intmax_t)get_first_zone(), (intmax_t)first_zone_data());
573 printf(_("Zonesize=%zu\n"), (size_t) MINIX_BLOCK_SIZE
<< get_zone_size());
574 printf(_("Maxsize=%zu\n\n"),get_max_size());
578 * Perform a test of a block; return the number of
579 * blocks readable/writable.
581 static size_t do_check(const struct fs_control
*ctl
, char * buffer
, int try, unsigned int current_block
) {
584 /* Seek to the correct loc. */
585 if (lseek(ctl
->device_fd
, current_block
* MINIX_BLOCK_SIZE
, SEEK_SET
) !=
586 current_block
* MINIX_BLOCK_SIZE
)
587 err(MKFS_EX_ERROR
, _("%s: seek failed during testing of blocks"),
591 got
= read(ctl
->device_fd
, buffer
, try * MINIX_BLOCK_SIZE
);
592 if (got
< 0) got
= 0;
593 if (got
& (MINIX_BLOCK_SIZE
- 1 )) {
594 printf(_("Weird values in do_check: probably bugs\n"));
596 got
/= MINIX_BLOCK_SIZE
;
600 static unsigned int currently_testing
= 0;
602 static void alarm_intr(int alnum
__attribute__ ((__unused__
))) {
603 unsigned long zones
= get_nzones();
605 if (currently_testing
>= zones
)
607 signal(SIGALRM
,alarm_intr
);
609 if (!currently_testing
)
611 printf("%d ...", currently_testing
);
615 static void check_blocks(struct fs_control
*ctl
) {
617 static char buffer
[MINIX_BLOCK_SIZE
* TEST_BUFFER_BLOCKS
];
618 unsigned long zones
= get_nzones();
619 unsigned long first_zone
= get_first_zone();
622 signal(SIGALRM
,alarm_intr
);
624 while (currently_testing
< zones
) {
625 if (lseek(ctl
->device_fd
, currently_testing
* MINIX_BLOCK_SIZE
,SEEK_SET
) !=
626 currently_testing
*MINIX_BLOCK_SIZE
)
627 errx(MKFS_EX_ERROR
, _("%s: seek failed in check_blocks"),
629 try = TEST_BUFFER_BLOCKS
;
630 if (currently_testing
+ try > zones
)
631 try = zones
-currently_testing
;
632 got
= do_check(ctl
, buffer
, try, currently_testing
);
633 currently_testing
+= got
;
636 if (currently_testing
< first_zone
)
637 errx(MKFS_EX_ERROR
, _("%s: bad blocks before data-area: "
638 "cannot make fs"), ctl
->device_name
);
639 mark_zone(currently_testing
);
640 ctl
->fs_bad_blocks
++;
643 if (ctl
->fs_bad_blocks
> 0)
644 printf(P_("%d bad block\n", "%d bad blocks\n", ctl
->fs_bad_blocks
), ctl
->fs_bad_blocks
);
647 static void get_list_blocks(struct fs_control
*ctl
, char *filename
) {
649 unsigned long blockno
;
651 listfile
= fopen(filename
,"r");
652 if (listfile
== NULL
)
653 err(MKFS_EX_ERROR
, _("%s: can't open file of bad blocks"),
656 while (!feof(listfile
)) {
657 if (fscanf(listfile
,"%lu\n", &blockno
) != 1) {
658 printf(_("badblock number input error on line %d\n"), ctl
->fs_bad_blocks
+ 1);
659 errx(MKFS_EX_ERROR
, _("%s: cannot read badblocks file"),
663 ctl
->fs_bad_blocks
++;
667 if (ctl
->fs_bad_blocks
> 0)
668 printf(P_("%d bad block\n", "%d bad blocks\n", ctl
->fs_bad_blocks
), ctl
->fs_bad_blocks
);
671 static int find_super_magic(const struct fs_control
*ctl
)
673 switch (fs_version
) {
675 if (ctl
->fs_namelen
== 14)
676 return MINIX_SUPER_MAGIC
;
677 return MINIX_SUPER_MAGIC2
;
679 if (ctl
->fs_namelen
== 14)
680 return MINIX2_SUPER_MAGIC
;
681 return MINIX2_SUPER_MAGIC2
;
683 return MINIX3_SUPER_MAGIC
;
689 static void determine_device_blocks(struct fs_control
*ctl
, const struct stat
*statbuf
)
691 unsigned long long dev_blocks
= 0;
693 if (S_ISBLK(statbuf
->st_mode
)) {
696 if (blkdev_get_sector_size(ctl
->device_fd
, §orsize
) == -1)
697 sectorsize
= DEFAULT_SECTOR_SIZE
; /* kernel < 2.3.3 */
698 if (MINIX_BLOCK_SIZE
< sectorsize
)
699 errx(MKFS_EX_ERROR
, _("block size smaller than physical "
700 "sector size of %s"), ctl
->device_name
);
701 if (blkdev_get_size(ctl
->device_fd
, &dev_blocks
) == -1)
702 errx(MKFS_EX_ERROR
, _("cannot determine size of %s"), ctl
->device_name
);
703 dev_blocks
/= MINIX_BLOCK_SIZE
;
704 } else if (!S_ISBLK(statbuf
->st_mode
))
705 dev_blocks
= statbuf
->st_size
/ MINIX_BLOCK_SIZE
;
707 ctl
->fs_blocks
= dev_blocks
;
708 else if (dev_blocks
< ctl
->fs_blocks
)
710 _("%s: requested blocks (%llu) exceeds available (%llu) blocks\n"),
711 ctl
->device_name
, ctl
->fs_blocks
, dev_blocks
);
712 if (ctl
->fs_blocks
< 10)
713 errx(MKFS_EX_ERROR
, _("%s: number of blocks too small"), ctl
->device_name
);
714 if (fs_version
== 1 && ctl
->fs_blocks
> MINIX_MAX_INODES
)
715 ctl
->fs_blocks
= MINIX_MAX_INODES
;
716 if (ctl
->fs_blocks
> (4 + ((MINIX_MAX_INODES
- 4) * BITS_PER_BLOCK
)))
717 ctl
->fs_blocks
= 4 + ((MINIX_MAX_INODES
- 4) * BITS_PER_BLOCK
); /* Utter maximum: Clip. */
720 static void check_user_instructions(struct fs_control
*ctl
)
722 switch (fs_version
) {
725 if (ctl
->fs_namelen
== 14 || ctl
->fs_namelen
== 30)
726 ctl
->fs_dirsize
= ctl
->fs_namelen
+ 2;
728 errx(MKFS_EX_ERROR
, _("unsupported name length: %d"), ctl
->fs_namelen
);
731 if (ctl
->fs_namelen
== 60)
732 ctl
->fs_dirsize
= ctl
->fs_namelen
+ 4;
734 errx(MKFS_EX_ERROR
, _("unsupported name length: %d"), ctl
->fs_namelen
);
737 errx(MKFS_EX_ERROR
, _("unsupported minix file system version: %d"), fs_version
);
739 ctl
->fs_magic
= find_super_magic(ctl
);
742 int main(int argc
, char ** argv
)
744 struct fs_control ctl
= {
745 .fs_namelen
= 30, /* keep in sync with DEFAULT_FS_VERSION */
750 char * listfile
= NULL
;
752 OPT_LOCK
= CHAR_MAX
+ 1
754 static const struct option longopts
[] = {
755 {"namelength", required_argument
, NULL
, 'n'},
756 {"inodes", required_argument
, NULL
, 'i'},
757 {"check", no_argument
, NULL
, 'c'},
758 {"badblocks", required_argument
, NULL
, 'l'},
759 {"version", no_argument
, NULL
, 'V'},
760 {"help", no_argument
, NULL
, 'h'},
761 {"lock",optional_argument
, NULL
, OPT_LOCK
},
765 setlocale(LC_ALL
, "");
766 bindtextdomain(PACKAGE
, LOCALEDIR
);
768 close_stdout_atexit();
770 strutils_set_exitcode(MKFS_EX_USAGE
);
772 while ((i
= getopt_long(argc
, argv
, "1v23n:i:cl:Vh", longopts
, NULL
)) != -1)
777 case 'v': /* kept for backwards compatibility */
778 warnx(_("-v is ambiguous, use '-2' instead"));
788 ctl
.fs_namelen
= strtou16_or_err(optarg
,
789 _("failed to parse maximum length of filenames"));
792 ctl
.fs_inodes
= strtoul_or_err(optarg
,
793 _("failed to parse number of inodes"));
796 ctl
.check_blocks
= 1;
806 ctl
.lockmode
= optarg
;
810 print_version(MKFS_EX_OK
);
814 errtryhelp(MKFS_EX_USAGE
);
819 ctl
.device_name
= argv
[0];
824 ctl
.fs_blocks
= strtoul_or_err(argv
[0], _("failed to parse number of blocks"));
826 if (!ctl
.device_name
) {
827 warnx(_("no device specified"));
828 errtryhelp(MKFS_EX_USAGE
);
830 check_user_instructions(&ctl
);
831 if (is_mounted(ctl
.device_name
))
832 errx(MKFS_EX_ERROR
, _("%s is mounted; will not make a filesystem here!"),
834 if (stat(ctl
.device_name
, &statbuf
) < 0)
835 err(MKFS_EX_ERROR
, _("stat of %s failed"), ctl
.device_name
);
836 ctl
.device_fd
= open_blkdev_or_file(&statbuf
, ctl
.device_name
, O_RDWR
);
837 if (ctl
.device_fd
< 0)
838 err(MKFS_EX_ERROR
, _("cannot open %s"), ctl
.device_name
);
839 if (blkdev_lock(ctl
.device_fd
, ctl
.device_name
, ctl
.lockmode
) != 0)
841 determine_device_blocks(&ctl
, &statbuf
);
843 if (ctl
.check_blocks
)
846 get_list_blocks(&ctl
, listfile
);
848 make_root_inode(&ctl
);
849 make_bad_inode(&ctl
);
851 mark_good_blocks(&ctl
);
853 if (close_fd(ctl
.device_fd
) != 0)
854 err(MKFS_EX_ERROR
, _("write failed"));