source: MondoRescue/branches/3.3/mindi-busybox/util-linux/mkfs_minix.c@ 3625

Last change on this file since 3625 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

File size: 18.3 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * mkfs.c - make a linux (minix) file-system.
4 *
5 * (C) 1991 Linus Torvalds.
6 *
7 * Licensed under GPLv2, see file LICENSE in this source tree.
8 */
9
10/*
11 * DD.MM.YY
12 *
13 * 24.11.91 - Time began. Used the fsck sources to get started.
14 *
15 * 25.11.91 - Corrected some bugs. Added support for ".badblocks"
16 * The algorithm for ".badblocks" is a bit weird, but
17 * it should work. Oh, well.
18 *
19 * 25.01.92 - Added the -l option for getting the list of bad blocks
20 * out of a named file. (Dave Rivers, rivers@ponds.uucp)
21 *
22 * 28.02.92 - Added %-information when using -c.
23 *
24 * 28.02.93 - Added support for other namelengths than the original
25 * 14 characters so that I can test the new kernel routines..
26 *
27 * 09.10.93 - Make exit status conform to that required by fsutil
28 * (Rik Faith, faith@cs.unc.edu)
29 *
30 * 31.10.93 - Added inode request feature, for backup floppies: use
31 * 32 inodes, for a news partition use more.
32 * (Scott Heavner, sdh@po.cwru.edu)
33 *
34 * 03.01.94 - Added support for file system valid flag.
35 * (Dr. Wettstein, greg%wind.uucp@plains.nodak.edu)
36 *
37 * 30.10.94 - added support for v2 filesystem
38 * (Andreas Schwab, schwab@issan.informatik.uni-dortmund.de)
39 *
40 * 09.11.94 - Added test to prevent overwrite of mounted fs adapted
41 * from Theodore Ts'o's (tytso@athena.mit.edu) mke2fs
42 * program. (Daniel Quinlan, quinlan@yggdrasil.com)
43 *
44 * 03.20.95 - Clear first 512 bytes of filesystem to make certain that
45 * the filesystem is not misidentified as a MS-DOS FAT filesystem.
46 * (Daniel Quinlan, quinlan@yggdrasil.com)
47 *
48 * 02.07.96 - Added small patch from Russell King to make the program a
49 * good deal more portable (janl@math.uio.no)
50 *
51 * Usage: mkfs [-c | -l filename ] [-v] [-nXX] [-iXX] device [size-in-blocks]
52 *
53 * -c for readability checking (SLOW!)
54 * -l for getting a list of bad blocks from a file.
55 * -n for namelength (currently the kernel only uses 14 or 30)
56 * -i for number of inodes
57 * -v for v2 filesystem
58 *
59 * The device may be a block device or a image of one, but this isn't
60 * enforced (but it's not much fun on a character device :-).
61 *
62 * Modified for BusyBox by Erik Andersen <andersen@debian.org> --
63 * removed getopt based parser and added a hand rolled one.
64 */
65
66//usage:#define mkfs_minix_trivial_usage
67//usage: "[-c | -l FILE] [-nXX] [-iXX] BLOCKDEV [KBYTES]"
68//usage:#define mkfs_minix_full_usage "\n\n"
69//usage: "Make a MINIX filesystem\n"
70//usage: "\n -c Check device for bad blocks"
71//usage: "\n -n [14|30] Maximum length of filenames"
72//usage: "\n -i INODES Number of inodes for the filesystem"
73//usage: "\n -l FILE Read bad blocks list from FILE"
74//usage: "\n -v Make version 2 filesystem"
75
76#include "libbb.h"
77#include <mntent.h>
78
79#include "minix.h"
80
81/* Store the very same times/uids/gids for image consistency */
82#if 1
83# define CUR_TIME 0
84# define GETUID 0
85# define GETGID 0
86#else
87/* Was using this. Is it useful? NB: this will break testsuite */
88# define CUR_TIME time(NULL)
89# define GETUID getuid()
90# define GETGID getgid()
91#endif
92
93enum {
94 MAX_GOOD_BLOCKS = 512,
95 TEST_BUFFER_BLOCKS = 16,
96};
97
98#if !ENABLE_FEATURE_MINIX2
99enum { version2 = 0 };
100#endif
101
102enum { dev_fd = 3 };
103
104struct globals {
105#if ENABLE_FEATURE_MINIX2
106 smallint version2;
107#define version2 G.version2
108#endif
109 char *device_name;
110 uint32_t total_blocks;
111 int badblocks;
112 int namelen;
113 int dirsize;
114 int magic;
115 char *inode_buffer;
116 char *inode_map;
117 char *zone_map;
118 int used_good_blocks;
119 unsigned long req_nr_inodes;
120 unsigned currently_testing;
121
122 char root_block[BLOCK_SIZE];
123 char superblock_buffer[BLOCK_SIZE];
124 char boot_block_buffer[512];
125 unsigned short good_blocks_table[MAX_GOOD_BLOCKS];
126 /* check_blocks(): buffer[] was the biggest static in entire bbox */
127 char check_blocks_buffer[BLOCK_SIZE * TEST_BUFFER_BLOCKS];
128
129 unsigned short ind_block1[BLOCK_SIZE >> 1];
130 unsigned short dind_block1[BLOCK_SIZE >> 1];
131 unsigned long ind_block2[BLOCK_SIZE >> 2];
132 unsigned long dind_block2[BLOCK_SIZE >> 2];
133};
134#define G (*ptr_to_globals)
135#define INIT_G() do { \
136 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
137} while (0)
138
139static ALWAYS_INLINE unsigned div_roundup(unsigned size, unsigned n)
140{
141 return (size + n-1) / n;
142}
143
144#define INODE_BUF1 (((struct minix1_inode*)G.inode_buffer) - 1)
145#define INODE_BUF2 (((struct minix2_inode*)G.inode_buffer) - 1)
146
147#define SB (*(struct minix_superblock*)G.superblock_buffer)
148
149#define SB_INODES (SB.s_ninodes)
150#define SB_IMAPS (SB.s_imap_blocks)
151#define SB_ZMAPS (SB.s_zmap_blocks)
152#define SB_FIRSTZONE (SB.s_firstdatazone)
153#define SB_ZONE_SIZE (SB.s_log_zone_size)
154#define SB_MAXSIZE (SB.s_max_size)
155#define SB_MAGIC (SB.s_magic)
156
157#if !ENABLE_FEATURE_MINIX2
158# define SB_ZONES (SB.s_nzones)
159# define INODE_BLOCKS div_roundup(SB_INODES, MINIX1_INODES_PER_BLOCK)
160#else
161# define SB_ZONES (version2 ? SB.s_zones : SB.s_nzones)
162# define INODE_BLOCKS div_roundup(SB_INODES, \
163 (version2 ? MINIX2_INODES_PER_BLOCK : MINIX1_INODES_PER_BLOCK))
164#endif
165
166#define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE)
167#define NORM_FIRSTZONE (2 + SB_IMAPS + SB_ZMAPS + INODE_BLOCKS)
168
169/* Before you ask "where they come from?": */
170/* setbit/clrbit are supplied by sys/param.h */
171
172static int minix_bit(const char* a, unsigned i)
173{
174 return a[i >> 3] & (1<<(i & 7));
175}
176
177static void minix_setbit(char *a, unsigned i)
178{
179 setbit(a, i);
180}
181static void minix_clrbit(char *a, unsigned i)
182{
183 clrbit(a, i);
184}
185
186/* Note: do not assume 0/1, it is 0/nonzero */
187#define zone_in_use(x) minix_bit(G.zone_map,(x)-SB_FIRSTZONE+1)
188/*#define inode_in_use(x) minix_bit(G.inode_map,(x))*/
189
190#define mark_inode(x) minix_setbit(G.inode_map,(x))
191#define unmark_inode(x) minix_clrbit(G.inode_map,(x))
192#define mark_zone(x) minix_setbit(G.zone_map,(x)-SB_FIRSTZONE+1)
193#define unmark_zone(x) minix_clrbit(G.zone_map,(x)-SB_FIRSTZONE+1)
194
195#ifndef BLKGETSIZE
196# define BLKGETSIZE _IO(0x12,96) /* return device size */
197#endif
198
199static void write_tables(void)
200{
201 /* Mark the superblock valid. */
202 SB.s_state |= MINIX_VALID_FS;
203 SB.s_state &= ~MINIX_ERROR_FS;
204
205 msg_eol = "seek to 0 failed";
206 xlseek(dev_fd, 0, SEEK_SET);
207
208 msg_eol = "can't clear boot sector";
209 xwrite(dev_fd, G.boot_block_buffer, 512);
210
211 msg_eol = "seek to BLOCK_SIZE failed";
212 xlseek(dev_fd, BLOCK_SIZE, SEEK_SET);
213
214 msg_eol = "can't write superblock";
215 xwrite(dev_fd, G.superblock_buffer, BLOCK_SIZE);
216
217 msg_eol = "can't write inode map";
218 xwrite(dev_fd, G.inode_map, SB_IMAPS * BLOCK_SIZE);
219
220 msg_eol = "can't write zone map";
221 xwrite(dev_fd, G.zone_map, SB_ZMAPS * BLOCK_SIZE);
222
223 msg_eol = "can't write inodes";
224 xwrite(dev_fd, G.inode_buffer, INODE_BUFFER_SIZE);
225
226 msg_eol = "\n";
227}
228
229static void write_block(int blk, char *buffer)
230{
231 xlseek(dev_fd, blk * BLOCK_SIZE, SEEK_SET);
232 xwrite(dev_fd, buffer, BLOCK_SIZE);
233}
234
235static int get_free_block(void)
236{
237 int blk;
238
239 if (G.used_good_blocks + 1 >= MAX_GOOD_BLOCKS)
240 bb_error_msg_and_die("too many bad blocks");
241 if (G.used_good_blocks)
242 blk = G.good_blocks_table[G.used_good_blocks - 1] + 1;
243 else
244 blk = SB_FIRSTZONE;
245 while (blk < SB_ZONES && zone_in_use(blk))
246 blk++;
247 if (blk >= SB_ZONES)
248 bb_error_msg_and_die("not enough good blocks");
249 G.good_blocks_table[G.used_good_blocks] = blk;
250 G.used_good_blocks++;
251 return blk;
252}
253
254static void mark_good_blocks(void)
255{
256 int blk;
257
258 for (blk = 0; blk < G.used_good_blocks; blk++)
259 mark_zone(G.good_blocks_table[blk]);
260}
261
262static int next(int zone)
263{
264 if (!zone)
265 zone = SB_FIRSTZONE - 1;
266 while (++zone < SB_ZONES)
267 if (zone_in_use(zone))
268 return zone;
269 return 0;
270}
271
272static void make_bad_inode(void)
273{
274 struct minix1_inode *inode = &INODE_BUF1[MINIX_BAD_INO];
275 int i, j, zone;
276 int ind = 0, dind = 0;
277 /* moved to globals to reduce stack usage
278 unsigned short ind_block[BLOCK_SIZE >> 1];
279 unsigned short dind_block[BLOCK_SIZE >> 1];
280 */
281#define ind_block (G.ind_block1)
282#define dind_block (G.dind_block1)
283
284#define NEXT_BAD (zone = next(zone))
285
286 if (!G.badblocks)
287 return;
288 mark_inode(MINIX_BAD_INO);
289 inode->i_nlinks = 1;
290 /* BTW, setting this makes all images different */
291 /* it's harder to check for bugs then - diff isn't helpful :(... */
292 inode->i_time = CUR_TIME;
293 inode->i_mode = S_IFREG + 0000;
294 inode->i_size = G.badblocks * BLOCK_SIZE;
295 zone = next(0);
296 for (i = 0; i < 7; i++) {
297 inode->i_zone[i] = zone;
298 if (!NEXT_BAD)
299 goto end_bad;
300 }
301 inode->i_zone[7] = ind = get_free_block();
302 memset(ind_block, 0, BLOCK_SIZE);
303 for (i = 0; i < 512; i++) {
304 ind_block[i] = zone;
305 if (!NEXT_BAD)
306 goto end_bad;
307 }
308 inode->i_zone[8] = dind = get_free_block();
309 memset(dind_block, 0, BLOCK_SIZE);
310 for (i = 0; i < 512; i++) {
311 write_block(ind, (char *) ind_block);
312 dind_block[i] = ind = get_free_block();
313 memset(ind_block, 0, BLOCK_SIZE);
314 for (j = 0; j < 512; j++) {
315 ind_block[j] = zone;
316 if (!NEXT_BAD)
317 goto end_bad;
318 }
319 }
320 bb_error_msg_and_die("too many bad blocks");
321 end_bad:
322 if (ind)
323 write_block(ind, (char *) ind_block);
324 if (dind)
325 write_block(dind, (char *) dind_block);
326#undef ind_block
327#undef dind_block
328}
329
330#if ENABLE_FEATURE_MINIX2
331static void make_bad_inode2(void)
332{
333 struct minix2_inode *inode = &INODE_BUF2[MINIX_BAD_INO];
334 int i, j, zone;
335 int ind = 0, dind = 0;
336 /* moved to globals to reduce stack usage
337 unsigned long ind_block[BLOCK_SIZE >> 2];
338 unsigned long dind_block[BLOCK_SIZE >> 2];
339 */
340#define ind_block (G.ind_block2)
341#define dind_block (G.dind_block2)
342
343 if (!G.badblocks)
344 return;
345 mark_inode(MINIX_BAD_INO);
346 inode->i_nlinks = 1;
347 inode->i_atime = inode->i_mtime = inode->i_ctime = CUR_TIME;
348 inode->i_mode = S_IFREG + 0000;
349 inode->i_size = G.badblocks * BLOCK_SIZE;
350 zone = next(0);
351 for (i = 0; i < 7; i++) {
352 inode->i_zone[i] = zone;
353 if (!NEXT_BAD)
354 goto end_bad;
355 }
356 inode->i_zone[7] = ind = get_free_block();
357 memset(ind_block, 0, BLOCK_SIZE);
358 for (i = 0; i < 256; i++) {
359 ind_block[i] = zone;
360 if (!NEXT_BAD)
361 goto end_bad;
362 }
363 inode->i_zone[8] = dind = get_free_block();
364 memset(dind_block, 0, BLOCK_SIZE);
365 for (i = 0; i < 256; i++) {
366 write_block(ind, (char *) ind_block);
367 dind_block[i] = ind = get_free_block();
368 memset(ind_block, 0, BLOCK_SIZE);
369 for (j = 0; j < 256; j++) {
370 ind_block[j] = zone;
371 if (!NEXT_BAD)
372 goto end_bad;
373 }
374 }
375 /* Could make triple indirect block here */
376 bb_error_msg_and_die("too many bad blocks");
377 end_bad:
378 if (ind)
379 write_block(ind, (char *) ind_block);
380 if (dind)
381 write_block(dind, (char *) dind_block);
382#undef ind_block
383#undef dind_block
384}
385#else
386void make_bad_inode2(void);
387#endif
388
389static void make_root_inode(void)
390{
391 struct minix1_inode *inode = &INODE_BUF1[MINIX_ROOT_INO];
392
393 mark_inode(MINIX_ROOT_INO);
394 inode->i_zone[0] = get_free_block();
395 inode->i_nlinks = 2;
396 inode->i_time = CUR_TIME;
397 if (G.badblocks)
398 inode->i_size = 3 * G.dirsize;
399 else {
400 G.root_block[2 * G.dirsize] = '\0';
401 G.root_block[2 * G.dirsize + 1] = '\0';
402 inode->i_size = 2 * G.dirsize;
403 }
404 inode->i_mode = S_IFDIR + 0755;
405 inode->i_uid = GETUID;
406 if (inode->i_uid)
407 inode->i_gid = GETGID;
408 write_block(inode->i_zone[0], G.root_block);
409}
410
411#if ENABLE_FEATURE_MINIX2
412static void make_root_inode2(void)
413{
414 struct minix2_inode *inode = &INODE_BUF2[MINIX_ROOT_INO];
415
416 mark_inode(MINIX_ROOT_INO);
417 inode->i_zone[0] = get_free_block();
418 inode->i_nlinks = 2;
419 inode->i_atime = inode->i_mtime = inode->i_ctime = CUR_TIME;
420 if (G.badblocks)
421 inode->i_size = 3 * G.dirsize;
422 else {
423 G.root_block[2 * G.dirsize] = '\0';
424 G.root_block[2 * G.dirsize + 1] = '\0';
425 inode->i_size = 2 * G.dirsize;
426 }
427 inode->i_mode = S_IFDIR + 0755;
428 inode->i_uid = GETUID;
429 if (inode->i_uid)
430 inode->i_gid = GETGID;
431 write_block(inode->i_zone[0], G.root_block);
432}
433#else
434void make_root_inode2(void);
435#endif
436
437/*
438 * Perform a test of a block; return the number of
439 * blocks readable.
440 */
441static size_t do_check(char *buffer, size_t try, unsigned current_block)
442{
443 ssize_t got;
444
445 /* Seek to the correct loc. */
446 msg_eol = "seek failed during testing of blocks";
447 xlseek(dev_fd, current_block * BLOCK_SIZE, SEEK_SET);
448 msg_eol = "\n";
449
450 /* Try the read */
451 got = read(dev_fd, buffer, try * BLOCK_SIZE);
452 if (got < 0)
453 got = 0;
454 try = ((size_t)got) / BLOCK_SIZE;
455
456 if (got & (BLOCK_SIZE - 1))
457 fprintf(stderr, "Short read at block %u\n", (unsigned)(current_block + try));
458 return try;
459}
460
461static void alarm_intr(int alnum UNUSED_PARAM)
462{
463 if (G.currently_testing >= SB_ZONES)
464 return;
465 signal(SIGALRM, alarm_intr);
466 alarm(5);
467 if (!G.currently_testing)
468 return;
469 printf("%d ...", G.currently_testing);
470 fflush_all();
471}
472
473static void check_blocks(void)
474{
475 size_t try, got;
476
477 G.currently_testing = 0;
478 signal(SIGALRM, alarm_intr);
479 alarm(5);
480 while (G.currently_testing < SB_ZONES) {
481 msg_eol = "seek failed in check_blocks";
482 xlseek(dev_fd, G.currently_testing * BLOCK_SIZE, SEEK_SET);
483 msg_eol = "\n";
484 try = TEST_BUFFER_BLOCKS;
485 if (G.currently_testing + try > SB_ZONES)
486 try = SB_ZONES - G.currently_testing;
487 got = do_check(G.check_blocks_buffer, try, G.currently_testing);
488 G.currently_testing += got;
489 if (got == try)
490 continue;
491 if (G.currently_testing < SB_FIRSTZONE)
492 bb_error_msg_and_die("bad blocks before data-area: cannot make fs");
493 mark_zone(G.currently_testing);
494 G.badblocks++;
495 G.currently_testing++;
496 }
497 alarm(0);
498 printf("%d bad block(s)\n", G.badblocks);
499}
500
501static void get_list_blocks(char *filename)
502{
503 FILE *listfile;
504 unsigned long blockno;
505
506 listfile = xfopen_for_read(filename);
507 while (!feof(listfile)) {
508 fscanf(listfile, "%lu\n", &blockno);
509 mark_zone(blockno);
510 G.badblocks++;
511 }
512 printf("%d bad block(s)\n", G.badblocks);
513}
514
515static void setup_tables(void)
516{
517 unsigned long inodes;
518 unsigned norm_firstzone;
519 unsigned sb_zmaps;
520 unsigned i;
521
522 /* memset(G.superblock_buffer, 0, BLOCK_SIZE); */
523 /* memset(G.boot_block_buffer, 0, 512); */
524 SB_MAGIC = G.magic;
525 SB_ZONE_SIZE = 0;
526 SB_MAXSIZE = version2 ? 0x7fffffff : (7 + 512 + 512 * 512) * 1024;
527 if (version2)
528 SB.s_zones = G.total_blocks;
529 else
530 SB.s_nzones = G.total_blocks;
531
532 /* some magic nrs: 1 inode / 3 blocks */
533 if (G.req_nr_inodes == 0)
534 inodes = G.total_blocks / 3;
535 else
536 inodes = G.req_nr_inodes;
537 /* Round up inode count to fill block size */
538 if (version2)
539 inodes = (inodes + MINIX2_INODES_PER_BLOCK - 1) &
540 ~(MINIX2_INODES_PER_BLOCK - 1);
541 else
542 inodes = (inodes + MINIX1_INODES_PER_BLOCK - 1) &
543 ~(MINIX1_INODES_PER_BLOCK - 1);
544 if (inodes > 65535)
545 inodes = 65535;
546 SB_INODES = inodes;
547 SB_IMAPS = div_roundup(SB_INODES + 1, BITS_PER_BLOCK);
548
549 /* Real bad hack but overwise mkfs.minix can be thrown
550 * in infinite loop...
551 * try:
552 * dd if=/dev/zero of=test.fs count=10 bs=1024
553 * mkfs.minix -i 200 test.fs
554 */
555 /* This code is not insane: NORM_FIRSTZONE is not a constant,
556 * it is calculated from SB_INODES, SB_IMAPS and SB_ZMAPS */
557 i = 999;
558 SB_ZMAPS = 0;
559 do {
560 norm_firstzone = NORM_FIRSTZONE;
561 sb_zmaps = div_roundup(G.total_blocks - norm_firstzone + 1, BITS_PER_BLOCK);
562 if (SB_ZMAPS == sb_zmaps) goto got_it;
563 SB_ZMAPS = sb_zmaps;
564 /* new SB_ZMAPS, need to recalc NORM_FIRSTZONE */
565 } while (--i);
566 bb_error_msg_and_die("incompatible size/inode count, try different -i N");
567 got_it:
568
569 SB_FIRSTZONE = norm_firstzone;
570 G.inode_map = xmalloc(SB_IMAPS * BLOCK_SIZE);
571 G.zone_map = xmalloc(SB_ZMAPS * BLOCK_SIZE);
572 memset(G.inode_map, 0xff, SB_IMAPS * BLOCK_SIZE);
573 memset(G.zone_map, 0xff, SB_ZMAPS * BLOCK_SIZE);
574 for (i = SB_FIRSTZONE; i < SB_ZONES; i++)
575 unmark_zone(i);
576 for (i = MINIX_ROOT_INO; i <= SB_INODES; i++)
577 unmark_inode(i);
578 G.inode_buffer = xzalloc(INODE_BUFFER_SIZE);
579 printf("%lu inodes\n", (unsigned long)SB_INODES);
580 printf("%lu blocks\n", (unsigned long)SB_ZONES);
581 printf("Firstdatazone=%lu (%lu)\n", (unsigned long)SB_FIRSTZONE, (unsigned long)norm_firstzone);
582 printf("Zonesize=%u\n", BLOCK_SIZE << SB_ZONE_SIZE);
583 printf("Maxsize=%lu\n", (unsigned long)SB_MAXSIZE);
584}
585
586int mkfs_minix_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
587int mkfs_minix_main(int argc UNUSED_PARAM, char **argv)
588{
589 unsigned opt;
590 char *tmp;
591 char *str_i;
592 char *listfile = NULL;
593
594 INIT_G();
595/* default (changed to 30, per Linus's suggestion, Sun Nov 21 08:05:07 1993) */
596 G.namelen = 30;
597 G.dirsize = 32;
598 G.magic = MINIX1_SUPER_MAGIC2;
599
600 if (INODE_SIZE1 * MINIX1_INODES_PER_BLOCK != BLOCK_SIZE)
601 bb_error_msg_and_die("bad inode size");
602#if ENABLE_FEATURE_MINIX2
603 if (INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE)
604 bb_error_msg_and_die("bad inode size");
605#endif
606
607 opt_complementary = "n+"; /* -n N */
608 opt = getopt32(argv, "ci:l:n:v", &str_i, &listfile, &G.namelen);
609 argv += optind;
610 //if (opt & 1) -c
611 if (opt & 2) G.req_nr_inodes = xatoul(str_i); // -i
612 //if (opt & 4) -l
613 if (opt & 8) { // -n
614 if (G.namelen == 14) G.magic = MINIX1_SUPER_MAGIC;
615 else if (G.namelen == 30) G.magic = MINIX1_SUPER_MAGIC2;
616 else bb_show_usage();
617 G.dirsize = G.namelen + 2;
618 }
619 if (opt & 0x10) { // -v
620#if ENABLE_FEATURE_MINIX2
621 version2 = 1;
622#else
623 bb_error_msg_and_die("not compiled with minix v2 support");
624#endif
625 }
626
627 G.device_name = argv[0];
628 if (!G.device_name)
629 bb_show_usage();
630
631 /* Check if it is mounted */
632 if (find_mount_point(G.device_name, 0))
633 bb_error_msg_and_die("can't format mounted filesystem");
634
635 xmove_fd(xopen(G.device_name, O_RDWR), dev_fd);
636
637 G.total_blocks = get_volume_size_in_bytes(dev_fd, argv[1], 1024, /*extend:*/ 1) / 1024;
638
639 if (G.total_blocks < 10)
640 bb_error_msg_and_die("must have at least 10 blocks");
641
642 if (version2) {
643 G.magic = MINIX2_SUPER_MAGIC2;
644 if (G.namelen == 14)
645 G.magic = MINIX2_SUPER_MAGIC;
646 } else if (G.total_blocks > 65535)
647 G.total_blocks = 65535;
648#if 0
649 struct stat statbuf;
650 xfstat(dev_fd, &statbuf, G.device_name);
651/* why? */
652 if (!S_ISBLK(statbuf.st_mode))
653 opt &= ~1; // clear -c (check)
654#if 0
655/* I don't know why someone has special code to prevent mkfs.minix
656 * on IDE devices. Why IDE but not SCSI, etc?... */
657 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
658 /* what is this? */
659 bb_error_msg_and_die("will not try "
660 "to make filesystem on '%s'", G.device_name);
661#endif
662#endif
663 tmp = G.root_block;
664 *(short *) tmp = 1;
665 strcpy(tmp + 2, ".");
666 tmp += G.dirsize;
667 *(short *) tmp = 1;
668 strcpy(tmp + 2, "..");
669 tmp += G.dirsize;
670 *(short *) tmp = 2;
671 strcpy(tmp + 2, ".badblocks");
672
673 setup_tables();
674
675 if (opt & 1) // -c ?
676 check_blocks();
677 else if (listfile)
678 get_list_blocks(listfile);
679
680 if (version2) {
681 make_root_inode2();
682 make_bad_inode2();
683 } else {
684 make_root_inode();
685 make_bad_inode();
686 }
687
688 mark_good_blocks();
689 write_tables();
690 return 0;
691}
Note: See TracBrowser for help on using the repository browser.