source: MondoRescue/branches/stable/mindi-busybox/util-linux/mkfs_minix.c@ 1770

Last change on this file since 1770 was 1770, checked in by Bruno Cornec, 16 years ago
  • Better output for mindi-busybox revision
  • Remove dummy file created on NFS - report from Arnaud Tiger <arnaud.tiger_at_hp.com>
  • strace useful for debug
  • fix new versions for pb (2.0.0 for mindi and 1.7.2 for mindi-busybox)
  • fix build process for mindi-busybox + options used in that version (dd for label-partitions-as-necessary)
  • fix typo in label-partitions-as-necessary which doesn't seem to work
  • Update to busybox 1.7.2
  • perl is now required at restore time to support uuid swap partitions (and will be used for many other thigs

in the future for sure)

  • next mindi version will be 2.0.0 due to all the changes made in it (udev may break working distros)
  • small optimization in mindi on keyboard handling (one single find instead of multiple)
  • better interaction for USB device when launching mindi manually
  • attempt to automatically guess block disk size for ramdisk
  • fix typos in bkphw
  • Fix the remaining problem with UUID support for swap partitions
  • Updates mondoarchive man page for USB support
  • Adds preliminary Hardware support to mindi (Proliant SSSTK)
  • Tries to add udev support also for rhel4
  • Fix UUID support which was still broken.
  • Be conservative in test for the start-nfs script
  • Update config file for mindi-busybox for 1.7.2 migration
  • Try to run around a busybox bug (1.2.2 pb on inexistant links)
  • Add build content for mindi-busybox in pb
  • Remove distributions content for mindi-busybox
  • Fix a warning on inexistant raidtab
  • Solve problem on tmpfs in restore init (Problem of inexistant symlink and busybox)
  • Create MONDO_CACHE and use it everywhere + creation at start
  • Really never try to eject a USB device
  • Fix a issue with &> usage (replaced with 1> and 2>)
  • Adds magic file to depllist in order to have file working + ldd which helps for debugging issues
  • tty modes correct to avoid sh error messages
  • Use ext3 normally and not ext2 instead
  • USB device should be corrected after reading (take 1st part)
  • Adds a mount_USB_here function derived from mount_CDROM_here
  • usb detection place before /dev detection in device name at restore time
  • Fix when restoring from USB: media is asked in interactive mode
  • Adds USB support for mondorestore
  • mount_cdrom => mount_media
  • elilo.efi is now searched throughout /boot/efi and not in a fixed place as there is no standard
  • untar-and-softlink => untar (+ interface change)
  • suppress useless softlinks creation/removal in boot process
  • avoids udevd messages on groups
  • Increase # of disks to 99 as in mindi at restore time (should be a conf file parameter)
  • skip existing big file creation
  • seems to work correctly for USB mindi boot
  • Adds group and tty link to udev conf
  • Always load usb-torage (even 2.6) to initiate USB bus discovery
  • Better printing of messages
  • Attempt to fix a bug in supporting OpenSusE 10.3 kernel for initramfs (mindi may now use multiple regex for kernel initrd detection)
  • Links were not correctly done as non relative for modules in mindi
  • exclusion of modules denied now works
  • Also create modules in their ordinary place, so that classical modprobe works + copy modules.dep
  • Fix bugs for DENY_MODS handling
  • Add device /dev/console for udev
  • ide-generic should now really be excluded
  • Fix a bug in major number for tty
  • If udev then adds modprobe/insmod to rootfs
  • tty0 is also cretaed with udev
  • ide-generic put rather in DENY_MODS
  • udevd remove from deplist s handled in mindi directly
  • better default for mindi when using --usb
  • Handles dynamically linked busybox (in case we want to use it soon ;-)
  • Adds fixed devices to create for udev
  • ide-generic should not be part of the initrd when using libata v2
  • support a dynamically linked udev (case on Ubuntu 7.10 and Mandriva 2008.0 so should be quite generic) This will give incitation to move to dyn. linked binaries in the initrd which will help for other tasks (ia6 4)
  • Improvement in udev support (do not use cl options not available in busybox)
  • Udev in mindi
    • auto creation of the right links at boot time with udev-links.conf(from Mandriva 2008.0)
    • rework startup of udev as current makes kernel crash (from Mandriva 2008.0)
    • add support for 64 bits udev
  • Try to render MyInsmod silent at boot time
  • Adds udev support (mandatory for newest distributions to avoid remapping of devices in a different way as on the original system)
  • We also need vaft format support for USB boot
  • Adds libusual support (Ubuntu 7.10 needs it for USB)
  • Improve Ubuntu/Debian keyboard detection and support
  • pbinit adapted to new pb (0.8.10). Filtering of docs done in it
  • Suppress some mondo warnings and errors on USB again
  • Tries to fix lack of files in deb mindi package
  • Verify should now work for USB devices
  • More log/mesages improvement for USB support
  • - Supress g_erase_tmpdir_and_scratchdir
  • Improve some log messages for USB support
  • Try to improve install in mindi to avoid issues with isolinux.cfg not installed vene if in the pkg :-(
  • Improve mindi-busybox build
  • In conformity with pb 0.8.9
  • Add support for Ubuntu 7.10 in build process
  • Add USB Key button to Menu UI (CD streamer removed)
  • Attempt to fix error messages on tmp/scratch files at the end by removing those dir at the latest possible.
  • Fix a bug linked to the size of the -E param which could be used (Arnaud Tiger/René Ribaud).
  • Integrate ~/.pbrc content into mondorescue.pb (required project-builder >= 0.8.7)
  • Put mondorescue in conformity with new pb filtering rules
  • Add USB support at restore time (no test done yet). New start-usb script PB varibale added where useful
  • Unmounting USB device before removal of temporary scratchdir
  • Stil refining USB copy back to mondo (one command was not executed)
  • No need to have the image subdor in the csratchdir when USB.
  • umount the USB partition before attempting to use it
  • Remove useless copy from mindi to mondo at end of USB handling

(risky merge, we are raising the limits of 2 diverging branches. The status of stable is not completely sure as such. Will need lots of tests, but it's not yet done :-()
(merge -r1692:1769 $SVN_M/branches/2.2.5)

File size: 18.1 KB
RevLine 
[821]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 *
[1770]36 * 30.10.94 - added support for v2 filesystem
37 * (Andreas Schwab, schwab@issan.informatik.uni-dortmund.de)
[821]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 readability 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
[1770]65#include "libbb.h"
[821]66#include <mntent.h>
67
[1770]68#include "minix.h"
[821]69
[1770]70#define DEBUG 0
[821]71
[1770]72/* If debugging, store the very same times/uids/gids for image consistency */
73#if DEBUG
74# define CUR_TIME 0
75# define GETUID 0
76# define GETGID 0
77#else
78# define CUR_TIME time(NULL)
79# define GETUID getuid()
80# define GETGID getgid()
81#endif
[821]82
[1770]83enum {
84 MAX_GOOD_BLOCKS = 512,
85 TEST_BUFFER_BLOCKS = 16,
[821]86};
87
[1770]88#if !ENABLE_FEATURE_MINIX2
89enum { version2 = 0 };
[821]90#endif
91
[1770]92struct globals {
93 int dev_fd;
[821]94
[1770]95#if ENABLE_FEATURE_MINIX2
96 smallint version2;
97#define version2 G.version2
[821]98#endif
[1770]99 char *device_name;
100 uint32_t total_blocks;
101 int badblocks;
102 int namelen;
103 int dirsize;
104 int magic;
105 char *inode_buffer;
106 char *inode_map;
107 char *zone_map;
108 int used_good_blocks;
109 unsigned long req_nr_inodes;
110 unsigned currently_testing;
[821]111
112
[1770]113 char root_block[BLOCK_SIZE];
114 char super_block_buffer[BLOCK_SIZE];
115 char boot_block_buffer[512];
116 unsigned short good_blocks_table[MAX_GOOD_BLOCKS];
117 /* check_blocks(): buffer[] was the biggest static in entire bbox */
118 char check_blocks_buffer[BLOCK_SIZE * TEST_BUFFER_BLOCKS];
119};
[821]120
[1770]121#define G (*ptr_to_globals)
[821]122
[1770]123static ALWAYS_INLINE unsigned div_roundup(unsigned size, unsigned n)
124{
125 return (size + n-1) / n;
126}
[821]127
[1770]128#define INODE_BUF1 (((struct minix1_inode*)G.inode_buffer) - 1)
129#define INODE_BUF2 (((struct minix2_inode*)G.inode_buffer) - 1)
[821]130
[1770]131#define SB (*(struct minix_super_block*)G.super_block_buffer)
[821]132
[1770]133#define SB_INODES (SB.s_ninodes)
134#define SB_IMAPS (SB.s_imap_blocks)
135#define SB_ZMAPS (SB.s_zmap_blocks)
136#define SB_FIRSTZONE (SB.s_firstdatazone)
137#define SB_ZONE_SIZE (SB.s_log_zone_size)
138#define SB_MAXSIZE (SB.s_max_size)
139#define SB_MAGIC (SB.s_magic)
[821]140
[1770]141#if !ENABLE_FEATURE_MINIX2
142# define SB_ZONES (SB.s_nzones)
143# define INODE_BLOCKS div_roundup(SB_INODES, MINIX1_INODES_PER_BLOCK)
[821]144#else
[1770]145# define SB_ZONES (version2 ? SB.s_zones : SB.s_nzones)
146# define INODE_BLOCKS div_roundup(SB_INODES, \
147 version2 ? MINIX2_INODES_PER_BLOCK : MINIX1_INODES_PER_BLOCK)
[821]148#endif
149
[1770]150#define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE)
151#define NORM_FIRSTZONE (2 + SB_IMAPS + SB_ZMAPS + INODE_BLOCKS)
[821]152
[1770]153/* Before you ask "where they come from?": */
154/* setbit/clrbit are supplied by sys/param.h */
[821]155
[1770]156static int minix_bit(const char* a, unsigned i)
[821]157{
[1770]158 return a[i >> 3] & (1<<(i & 7));
[821]159}
160
[1770]161static void minix_setbit(char *a, unsigned i)
162{
163 setbit(a, i);
164}
165static void minix_clrbit(char *a, unsigned i)
166{
167 clrbit(a, i);
168}
[821]169
[1770]170/* Note: do not assume 0/1, it is 0/nonzero */
171#define zone_in_use(x) minix_bit(G.zone_map,(x)-SB_FIRSTZONE+1)
172/*#define inode_in_use(x) minix_bit(G.inode_map,(x))*/
[821]173
[1770]174#define mark_inode(x) minix_setbit(G.inode_map,(x))
175#define unmark_inode(x) minix_clrbit(G.inode_map,(x))
176#define mark_zone(x) minix_setbit(G.zone_map,(x)-SB_FIRSTZONE+1)
177#define unmark_zone(x) minix_clrbit(G.zone_map,(x)-SB_FIRSTZONE+1)
[821]178
[1770]179#ifndef BLKGETSIZE
180# define BLKGETSIZE _IO(0x12,96) /* return device size */
181#endif
[821]182
183
184static long valid_offset(int fd, int offset)
185{
186 char ch;
187
[1770]188 if (lseek(fd, offset, SEEK_SET) < 0)
[821]189 return 0;
190 if (read(fd, &ch, 1) < 1)
191 return 0;
192 return 1;
193}
194
[1770]195static int count_blocks(int fd)
[821]196{
197 int high, low;
198
199 low = 0;
200 for (high = 1; valid_offset(fd, high); high *= 2)
201 low = high;
[1770]202
[821]203 while (low < high - 1) {
204 const int mid = (low + high) / 2;
205
206 if (valid_offset(fd, mid))
207 low = mid;
208 else
209 high = mid;
210 }
211 valid_offset(fd, 0);
212 return (low + 1);
213}
214
[1770]215static int get_size(const char *file)
[821]216{
217 int fd;
218 long size;
219
[1770]220 fd = xopen(file, O_RDWR);
[821]221 if (ioctl(fd, BLKGETSIZE, &size) >= 0) {
222 close(fd);
223 return (size * 512);
224 }
225
226 size = count_blocks(fd);
227 close(fd);
228 return size;
229}
230
[1770]231static void write_tables(void)
[821]232{
233 /* Mark the super block valid. */
[1770]234 SB.s_state |= MINIX_VALID_FS;
235 SB.s_state &= ~MINIX_ERROR_FS;
[821]236
[1770]237 msg_eol = "seek to 0 failed";
238 xlseek(G.dev_fd, 0, SEEK_SET);
[821]239
[1770]240 msg_eol = "cannot clear boot sector";
241 xwrite(G.dev_fd, G.boot_block_buffer, 512);
242
243 msg_eol = "seek to BLOCK_SIZE failed";
244 xlseek(G.dev_fd, BLOCK_SIZE, SEEK_SET);
245
246 msg_eol = "cannot write superblock";
247 xwrite(G.dev_fd, G.super_block_buffer, BLOCK_SIZE);
248
249 msg_eol = "cannot write inode map";
250 xwrite(G.dev_fd, G.inode_map, SB_IMAPS * BLOCK_SIZE);
251
252 msg_eol = "cannot write zone map";
253 xwrite(G.dev_fd, G.zone_map, SB_ZMAPS * BLOCK_SIZE);
254
255 msg_eol = "cannot write inodes";
256 xwrite(G.dev_fd, G.inode_buffer, INODE_BUFFER_SIZE);
257
258 msg_eol = "\n";
[821]259}
260
261static void write_block(int blk, char *buffer)
262{
[1770]263 xlseek(G.dev_fd, blk * BLOCK_SIZE, SEEK_SET);
264 xwrite(G.dev_fd, buffer, BLOCK_SIZE);
[821]265}
266
267static int get_free_block(void)
268{
269 int blk;
270
[1770]271 if (G.used_good_blocks + 1 >= MAX_GOOD_BLOCKS)
[821]272 bb_error_msg_and_die("too many bad blocks");
[1770]273 if (G.used_good_blocks)
274 blk = G.good_blocks_table[G.used_good_blocks - 1] + 1;
[821]275 else
[1770]276 blk = SB_FIRSTZONE;
277 while (blk < SB_ZONES && zone_in_use(blk))
[821]278 blk++;
[1770]279 if (blk >= SB_ZONES)
[821]280 bb_error_msg_and_die("not enough good blocks");
[1770]281 G.good_blocks_table[G.used_good_blocks] = blk;
282 G.used_good_blocks++;
[821]283 return blk;
284}
285
[1770]286static void mark_good_blocks(void)
[821]287{
288 int blk;
289
[1770]290 for (blk = 0; blk < G.used_good_blocks; blk++)
291 mark_zone(G.good_blocks_table[blk]);
[821]292}
293
294static int next(int zone)
295{
296 if (!zone)
[1770]297 zone = SB_FIRSTZONE - 1;
298 while (++zone < SB_ZONES)
[821]299 if (zone_in_use(zone))
300 return zone;
301 return 0;
302}
303
[1770]304static void make_bad_inode(void)
[821]305{
[1770]306 struct minix1_inode *inode = &INODE_BUF1[MINIX_BAD_INO];
[821]307 int i, j, zone;
308 int ind = 0, dind = 0;
309 unsigned short ind_block[BLOCK_SIZE >> 1];
310 unsigned short dind_block[BLOCK_SIZE >> 1];
311
312#define NEXT_BAD (zone = next(zone))
313
[1770]314 if (!G.badblocks)
[821]315 return;
316 mark_inode(MINIX_BAD_INO);
317 inode->i_nlinks = 1;
[1770]318 /* BTW, setting this makes all images different */
319 /* it's harder to check for bugs then - diff isn't helpful :(... */
320 inode->i_time = CUR_TIME;
[821]321 inode->i_mode = S_IFREG + 0000;
[1770]322 inode->i_size = G.badblocks * BLOCK_SIZE;
[821]323 zone = next(0);
324 for (i = 0; i < 7; i++) {
325 inode->i_zone[i] = zone;
326 if (!NEXT_BAD)
327 goto end_bad;
328 }
329 inode->i_zone[7] = ind = get_free_block();
330 memset(ind_block, 0, BLOCK_SIZE);
331 for (i = 0; i < 512; i++) {
332 ind_block[i] = zone;
333 if (!NEXT_BAD)
334 goto end_bad;
335 }
336 inode->i_zone[8] = dind = get_free_block();
337 memset(dind_block, 0, BLOCK_SIZE);
338 for (i = 0; i < 512; i++) {
339 write_block(ind, (char *) ind_block);
340 dind_block[i] = ind = get_free_block();
341 memset(ind_block, 0, BLOCK_SIZE);
342 for (j = 0; j < 512; j++) {
343 ind_block[j] = zone;
344 if (!NEXT_BAD)
345 goto end_bad;
346 }
347 }
348 bb_error_msg_and_die("too many bad blocks");
[1770]349 end_bad:
[821]350 if (ind)
351 write_block(ind, (char *) ind_block);
352 if (dind)
353 write_block(dind, (char *) dind_block);
354}
355
[1770]356#if ENABLE_FEATURE_MINIX2
357static void make_bad_inode2(void)
[821]358{
[1770]359 struct minix2_inode *inode = &INODE_BUF2[MINIX_BAD_INO];
[821]360 int i, j, zone;
361 int ind = 0, dind = 0;
362 unsigned long ind_block[BLOCK_SIZE >> 2];
363 unsigned long dind_block[BLOCK_SIZE >> 2];
364
[1770]365 if (!G.badblocks)
[821]366 return;
367 mark_inode(MINIX_BAD_INO);
368 inode->i_nlinks = 1;
[1770]369 inode->i_atime = inode->i_mtime = inode->i_ctime = CUR_TIME;
[821]370 inode->i_mode = S_IFREG + 0000;
[1770]371 inode->i_size = G.badblocks * BLOCK_SIZE;
[821]372 zone = next(0);
373 for (i = 0; i < 7; i++) {
374 inode->i_zone[i] = zone;
375 if (!NEXT_BAD)
376 goto end_bad;
377 }
378 inode->i_zone[7] = ind = get_free_block();
379 memset(ind_block, 0, BLOCK_SIZE);
380 for (i = 0; i < 256; i++) {
381 ind_block[i] = zone;
382 if (!NEXT_BAD)
383 goto end_bad;
384 }
385 inode->i_zone[8] = dind = get_free_block();
386 memset(dind_block, 0, BLOCK_SIZE);
387 for (i = 0; i < 256; i++) {
388 write_block(ind, (char *) ind_block);
389 dind_block[i] = ind = get_free_block();
390 memset(ind_block, 0, BLOCK_SIZE);
391 for (j = 0; j < 256; j++) {
392 ind_block[j] = zone;
393 if (!NEXT_BAD)
394 goto end_bad;
395 }
396 }
397 /* Could make triple indirect block here */
398 bb_error_msg_and_die("too many bad blocks");
[1770]399 end_bad:
[821]400 if (ind)
401 write_block(ind, (char *) ind_block);
402 if (dind)
403 write_block(dind, (char *) dind_block);
404}
[1770]405#else
406void make_bad_inode2(void);
[821]407#endif
408
[1770]409static void make_root_inode(void)
[821]410{
[1770]411 struct minix1_inode *inode = &INODE_BUF1[MINIX_ROOT_INO];
[821]412
413 mark_inode(MINIX_ROOT_INO);
414 inode->i_zone[0] = get_free_block();
415 inode->i_nlinks = 2;
[1770]416 inode->i_time = CUR_TIME;
417 if (G.badblocks)
418 inode->i_size = 3 * G.dirsize;
[821]419 else {
[1770]420 G.root_block[2 * G.dirsize] = '\0';
421 G.root_block[2 * G.dirsize + 1] = '\0';
422 inode->i_size = 2 * G.dirsize;
[821]423 }
424 inode->i_mode = S_IFDIR + 0755;
[1770]425 inode->i_uid = GETUID;
[821]426 if (inode->i_uid)
[1770]427 inode->i_gid = GETGID;
428 write_block(inode->i_zone[0], G.root_block);
[821]429}
430
[1770]431#if ENABLE_FEATURE_MINIX2
432static void make_root_inode2(void)
[821]433{
[1770]434 struct minix2_inode *inode = &INODE_BUF2[MINIX_ROOT_INO];
[821]435
436 mark_inode(MINIX_ROOT_INO);
437 inode->i_zone[0] = get_free_block();
438 inode->i_nlinks = 2;
[1770]439 inode->i_atime = inode->i_mtime = inode->i_ctime = CUR_TIME;
440 if (G.badblocks)
441 inode->i_size = 3 * G.dirsize;
[821]442 else {
[1770]443 G.root_block[2 * G.dirsize] = '\0';
444 G.root_block[2 * G.dirsize + 1] = '\0';
445 inode->i_size = 2 * G.dirsize;
[821]446 }
447 inode->i_mode = S_IFDIR + 0755;
[1770]448 inode->i_uid = GETUID;
[821]449 if (inode->i_uid)
[1770]450 inode->i_gid = GETGID;
451 write_block(inode->i_zone[0], G.root_block);
[821]452}
[1770]453#else
454void make_root_inode2(void);
[821]455#endif
456
457/*
458 * Perform a test of a block; return the number of
[1770]459 * blocks readable.
[821]460 */
[1770]461static size_t do_check(char *buffer, size_t try, unsigned current_block)
[821]462{
[1770]463 ssize_t got;
[821]464
465 /* Seek to the correct loc. */
[1770]466 msg_eol = "seek failed during testing of blocks";
467 xlseek(G.dev_fd, current_block * BLOCK_SIZE, SEEK_SET);
468 msg_eol = "\n";
[821]469
470 /* Try the read */
[1770]471 got = read(G.dev_fd, buffer, try * BLOCK_SIZE);
[821]472 if (got < 0)
473 got = 0;
[1770]474 try = ((size_t)got) / BLOCK_SIZE;
475
476 if (got & (BLOCK_SIZE - 1))
477 fprintf(stderr, "Short read at block %u\n", (unsigned)(current_block + try));
478 return try;
[821]479}
480
481static void alarm_intr(int alnum)
482{
[1770]483 if (G.currently_testing >= SB_ZONES)
[821]484 return;
485 signal(SIGALRM, alarm_intr);
486 alarm(5);
[1770]487 if (!G.currently_testing)
[821]488 return;
[1770]489 printf("%d ...", G.currently_testing);
[821]490 fflush(stdout);
491}
492
493static void check_blocks(void)
494{
[1770]495 size_t try, got;
[821]496
[1770]497 G.currently_testing = 0;
[821]498 signal(SIGALRM, alarm_intr);
499 alarm(5);
[1770]500 while (G.currently_testing < SB_ZONES) {
501 msg_eol = "seek failed in check_blocks";
502 xlseek(G.dev_fd, G.currently_testing * BLOCK_SIZE, SEEK_SET);
503 msg_eol = "\n";
[821]504 try = TEST_BUFFER_BLOCKS;
[1770]505 if (G.currently_testing + try > SB_ZONES)
506 try = SB_ZONES - G.currently_testing;
507 got = do_check(G.check_blocks_buffer, try, G.currently_testing);
508 G.currently_testing += got;
[821]509 if (got == try)
510 continue;
[1770]511 if (G.currently_testing < SB_FIRSTZONE)
[821]512 bb_error_msg_and_die("bad blocks before data-area: cannot make fs");
[1770]513 mark_zone(G.currently_testing);
514 G.badblocks++;
515 G.currently_testing++;
[821]516 }
[1770]517 alarm(0);
518 printf("%d bad block(s)\n", G.badblocks);
[821]519}
520
521static void get_list_blocks(char *filename)
522{
523 FILE *listfile;
524 unsigned long blockno;
525
[1770]526 listfile = xfopen(filename, "r");
[821]527 while (!feof(listfile)) {
528 fscanf(listfile, "%ld\n", &blockno);
529 mark_zone(blockno);
[1770]530 G.badblocks++;
[821]531 }
[1770]532 printf("%d bad block(s)\n", G.badblocks);
[821]533}
534
[1770]535static void setup_tables(void)
536{
537 unsigned long inodes;
538 unsigned norm_firstzone;
539 unsigned sb_zmaps;
540 unsigned i;
541
542 /* memset(G.super_block_buffer, 0, BLOCK_SIZE); */
543 /* memset(G.boot_block_buffer, 0, 512); */
544 SB_MAGIC = G.magic;
545 SB_ZONE_SIZE = 0;
546 SB_MAXSIZE = version2 ? 0x7fffffff : (7 + 512 + 512 * 512) * 1024;
547 if (version2)
548 SB.s_zones = G.total_blocks;
549 else
550 SB.s_nzones = G.total_blocks;
551
552 /* some magic nrs: 1 inode / 3 blocks */
553 if (G.req_nr_inodes == 0)
554 inodes = G.total_blocks / 3;
555 else
556 inodes = G.req_nr_inodes;
557 /* Round up inode count to fill block size */
558 if (version2)
559 inodes = (inodes + MINIX2_INODES_PER_BLOCK - 1) &
560 ~(MINIX2_INODES_PER_BLOCK - 1);
561 else
562 inodes = (inodes + MINIX1_INODES_PER_BLOCK - 1) &
563 ~(MINIX1_INODES_PER_BLOCK - 1);
564 if (inodes > 65535)
565 inodes = 65535;
566 SB_INODES = inodes;
567 SB_IMAPS = div_roundup(SB_INODES + 1, BITS_PER_BLOCK);
568
569 /* Real bad hack but overwise mkfs.minix can be thrown
570 * in infinite loop...
571 * try:
572 * dd if=/dev/zero of=test.fs count=10 bs=1024
573 * mkfs.minix -i 200 test.fs
574 */
575 /* This code is not insane: NORM_FIRSTZONE is not a constant,
576 * it is calculated from SB_INODES, SB_IMAPS and SB_ZMAPS */
577 i = 999;
578 SB_ZMAPS = 0;
579 do {
580 norm_firstzone = NORM_FIRSTZONE;
581 sb_zmaps = div_roundup(G.total_blocks - norm_firstzone + 1, BITS_PER_BLOCK);
582 if (SB_ZMAPS == sb_zmaps) goto got_it;
583 SB_ZMAPS = sb_zmaps;
584 /* new SB_ZMAPS, need to recalc NORM_FIRSTZONE */
585 } while (--i);
586 bb_error_msg_and_die("incompatible size/inode count, try different -i N");
587 got_it:
588
589 SB_FIRSTZONE = norm_firstzone;
590 G.inode_map = xmalloc(SB_IMAPS * BLOCK_SIZE);
591 G.zone_map = xmalloc(SB_ZMAPS * BLOCK_SIZE);
592 memset(G.inode_map, 0xff, SB_IMAPS * BLOCK_SIZE);
593 memset(G.zone_map, 0xff, SB_ZMAPS * BLOCK_SIZE);
594 for (i = SB_FIRSTZONE; i < SB_ZONES; i++)
595 unmark_zone(i);
596 for (i = MINIX_ROOT_INO; i <= SB_INODES; i++)
597 unmark_inode(i);
598 G.inode_buffer = xzalloc(INODE_BUFFER_SIZE);
599 printf("%ld inodes\n", (long)SB_INODES);
600 printf("%ld blocks\n", (long)SB_ZONES);
601 printf("Firstdatazone=%ld (%ld)\n", (long)SB_FIRSTZONE, (long)norm_firstzone);
602 printf("Zonesize=%d\n", BLOCK_SIZE << SB_ZONE_SIZE);
603 printf("Maxsize=%ld\n", (long)SB_MAXSIZE);
604}
605
606int mkfs_minix_main(int argc, char **argv);
[821]607int mkfs_minix_main(int argc, char **argv)
608{
[1770]609 struct mntent *mp;
610 unsigned opt;
[821]611 char *tmp;
612 struct stat statbuf;
[1770]613 char *str_i, *str_n;
[821]614 char *listfile = NULL;
615
[1770]616 PTR_TO_GLOBALS = xzalloc(sizeof(G));
617/* default (changed to 30, per Linus's suggestion, Sun Nov 21 08:05:07 1993) */
618 G.namelen = 30;
619 G.dirsize = 32;
620 G.magic = MINIX1_SUPER_MAGIC2;
621
622 if (INODE_SIZE1 * MINIX1_INODES_PER_BLOCK != BLOCK_SIZE)
[821]623 bb_error_msg_and_die("bad inode size");
[1770]624#if ENABLE_FEATURE_MINIX2
[821]625 if (INODE_SIZE2 * MINIX2_INODES_PER_BLOCK != BLOCK_SIZE)
626 bb_error_msg_and_die("bad inode size");
627#endif
628
[1770]629 opt = getopt32(argv, "ci:l:n:v", &str_i, &listfile, &str_n);
630 argv += optind;
631 //if (opt & 1) -c
632 if (opt & 2) G.req_nr_inodes = xatoul(str_i); // -i
633 //if (opt & 4) -l
634 if (opt & 8) { // -n
635 G.namelen = xatoi_u(str_n);
636 if (G.namelen == 14) G.magic = MINIX1_SUPER_MAGIC;
637 else if (G.namelen == 30) G.magic = MINIX1_SUPER_MAGIC2;
638 else bb_show_usage();
639 G.dirsize = G.namelen + 2;
640 }
641 if (opt & 0x10) { // -v
642#if ENABLE_FEATURE_MINIX2
643 version2 = 1;
[821]644#else
[1770]645 bb_error_msg_and_die("not compiled with minix v2 support");
[821]646#endif
647 }
648
[1770]649 G.device_name = *argv++;
650 if (!G.device_name)
[821]651 bb_show_usage();
[1770]652 if (*argv)
653 G.total_blocks = xatou32(*argv);
654 else
655 G.total_blocks = get_size(G.device_name) / 1024;
656
657 if (G.total_blocks < 10)
658 bb_error_msg_and_die("must have at least 10 blocks");
659
[821]660 if (version2) {
[1770]661 G.magic = MINIX2_SUPER_MAGIC2;
662 if (G.namelen == 14)
663 G.magic = MINIX2_SUPER_MAGIC;
664 } else if (G.total_blocks > 65535)
665 G.total_blocks = 65535;
666
667 /* Check if it is mounted */
668 mp = find_mount_point(G.device_name, NULL);
669 if (mp && strcmp(G.device_name, mp->mnt_fsname) == 0)
670 bb_error_msg_and_die("%s is mounted on %s; "
671 "refusing to make a filesystem",
672 G.device_name, mp->mnt_dir);
673
674 G.dev_fd = xopen(G.device_name, O_RDWR);
675 if (fstat(G.dev_fd, &statbuf) < 0)
676 bb_error_msg_and_die("cannot stat %s", G.device_name);
677 if (!S_ISBLK(statbuf.st_mode))
678 opt &= ~1; // clear -c (check)
679
680/* I don't know why someone has special code to prevent mkfs.minix
681 * on IDE devices. Why IDE but not SCSI, etc?... */
682#if 0
683 else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340)
684 /* what is this? */
685 bb_error_msg_and_die("will not try "
686 "to make filesystem on '%s'", G.device_name);
[821]687#endif
[1770]688
689 tmp = G.root_block;
[821]690 *(short *) tmp = 1;
691 strcpy(tmp + 2, ".");
[1770]692 tmp += G.dirsize;
[821]693 *(short *) tmp = 1;
694 strcpy(tmp + 2, "..");
[1770]695 tmp += G.dirsize;
[821]696 *(short *) tmp = 2;
697 strcpy(tmp + 2, ".badblocks");
[1770]698
[821]699 setup_tables();
[1770]700
701 if (opt & 1) // -c ?
[821]702 check_blocks();
703 else if (listfile)
704 get_list_blocks(listfile);
[1770]705
[821]706 if (version2) {
707 make_root_inode2();
708 make_bad_inode2();
[1770]709 } else {
[821]710 make_root_inode();
711 make_bad_inode();
712 }
[1770]713
[821]714 mark_good_blocks();
715 write_tables();
716 return 0;
717}
Note: See TracBrowser for help on using the repository browser.