]>
Commit | Line | Data |
---|---|---|
6dbe3af9 KZ |
1 | /* |
2 | * mkfs.c - make a linux (minix) file-system. | |
3 | * | |
4 | * (C) 1991 Linus Torvalds. This file may be redistributed as per | |
5 | * the Linux copyright. | |
6 | */ | |
7 | ||
8 | /* | |
726f69e2 | 9 | * DD.MM.YY |
6dbe3af9 | 10 | * |
726f69e2 KZ |
11 | * 24.11.91 - Time began. Used the fsck sources to get started. |
12 | * | |
13 | * 25.11.91 - Corrected some bugs. Added support for ".badblocks" | |
6dbe3af9 KZ |
14 | * The algorithm for ".badblocks" is a bit weird, but |
15 | * it should work. Oh, well. | |
16 | * | |
726f69e2 KZ |
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) | |
6dbe3af9 | 19 | * |
726f69e2 | 20 | * 28.02.92 - Added %-information when using -c. |
6dbe3af9 | 21 | * |
726f69e2 | 22 | * 28.02.93 - Added support for other namelengths than the original |
6dbe3af9 KZ |
23 | * 14 characters so that I can test the new kernel routines.. |
24 | * | |
726f69e2 KZ |
25 | * 09.10.93 - Make exit status conform to that required by fsutil |
26 | * (Rik Faith, faith@cs.unc.edu) | |
6dbe3af9 | 27 | * |
726f69e2 KZ |
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) | |
6dbe3af9 | 31 | * |
726f69e2 KZ |
32 | * 03.01.94 - Added support for file system valid flag. |
33 | * (Dr. Wettstein, greg%wind.uucp@plains.nodak.edu) | |
6dbe3af9 | 34 | * |
726f69e2 KZ |
35 | * 09.11.94 - Added test to prevent overwrite of mounted fs adapted |
36 | * from Theodore Ts'o's (tytso@athena.mit.edu) mke2fs | |
37 | * program. (Daniel Quinlan, quinlan@yggdrasil.com) | |
38 | * | |
39 | * 03.20.95 - Clear first 512 bytes of filesystem to make certain that | |
40 | * the filesystem is not misidentified as a MS-DOS FAT filesystem. | |
41 | * (Daniel Quinlan, quinlan@yggdrasil.com) | |
6dbe3af9 KZ |
42 | * |
43 | * Usage: mkfs [-c] [-nXX] [-iXX] device size-in-blocks | |
44 | * mkfs [-l filename ] device size-in-blocks | |
45 | * | |
46 | * -c for readablility checking (SLOW!) | |
47 | * -l for getting a list of bad blocks from a file. | |
48 | * -n for namelength (currently the kernel only uses 14 or 30) | |
49 | * -i for number of inodes | |
50 | * | |
51 | * The device may be a block device or a image of one, but this isn't | |
52 | * enforced (but it's not much fun on a character device :-). | |
53 | */ | |
54 | ||
55 | #include <stdio.h> | |
56 | #include <time.h> | |
57 | #include <unistd.h> | |
58 | #include <string.h> | |
59 | #include <signal.h> | |
60 | #include <fcntl.h> | |
61 | #include <ctype.h> | |
62 | #include <stdlib.h> | |
63 | #include <termios.h> | |
64 | #include <sys/stat.h> | |
65 | #include <mntent.h> | |
66 | ||
67 | #include <linux/fs.h> | |
68 | #include <linux/minix_fs.h> | |
69 | ||
70 | #ifndef __GNUC__ | |
71 | #error "needs gcc for the bitop-__asm__'s" | |
72 | #endif | |
73 | ||
74 | #ifndef __linux__ | |
75 | #define volatile | |
76 | #endif | |
77 | ||
78 | #define MINIX_ROOT_INO 1 | |
79 | #define MINIX_BAD_INO 2 | |
80 | ||
81 | #define TEST_BUFFER_BLOCKS 16 | |
82 | #define MAX_GOOD_BLOCKS 512 | |
83 | ||
84 | #define UPPER(size,n) ((size+((n)-1))/(n)) | |
85 | #define INODE_SIZE (sizeof(struct minix_inode)) | |
86 | #define INODE_BLOCKS UPPER(INODES,MINIX_INODES_PER_BLOCK) | |
87 | #define INODE_BUFFER_SIZE (INODE_BLOCKS * BLOCK_SIZE) | |
88 | ||
89 | #define BITS_PER_BLOCK (BLOCK_SIZE<<3) | |
90 | ||
91 | static char * program_name = "mkfs"; | |
92 | static char * device_name = NULL; | |
93 | static int DEV = -1; | |
94 | static long BLOCKS = 0; | |
95 | static int check = 0; | |
96 | static int badblocks = 0; | |
97 | static int namelen = 30; /* default (changed to 30, per Linus's | |
98 | suggestion, Sun Nov 21 08:05:07 1993) */ | |
99 | static int dirsize = 16; | |
100 | static int magic = MINIX_SUPER_MAGIC; | |
101 | ||
102 | static char root_block[BLOCK_SIZE] = "\0"; | |
103 | ||
104 | static char * inode_buffer = NULL; | |
105 | #define Inode (((struct minix_inode *) inode_buffer)-1) | |
106 | static char super_block_buffer[BLOCK_SIZE]; | |
726f69e2 | 107 | static char boot_block_buffer[512]; |
6dbe3af9 KZ |
108 | #define Super (*(struct minix_super_block *)super_block_buffer) |
109 | #define INODES ((unsigned long)Super.s_ninodes) | |
110 | #define ZONES ((unsigned long)Super.s_nzones) | |
111 | #define IMAPS ((unsigned long)Super.s_imap_blocks) | |
112 | #define ZMAPS ((unsigned long)Super.s_zmap_blocks) | |
113 | #define FIRSTZONE ((unsigned long)Super.s_firstdatazone) | |
114 | #define ZONESIZE ((unsigned long)Super.s_log_zone_size) | |
115 | #define MAXSIZE ((unsigned long)Super.s_max_size) | |
116 | #define MAGIC (Super.s_magic) | |
117 | #define NORM_FIRSTZONE (2+IMAPS+ZMAPS+INODE_BLOCKS) | |
118 | ||
119 | static char inode_map[BLOCK_SIZE * MINIX_I_MAP_SLOTS]; | |
120 | static char zone_map[BLOCK_SIZE * MINIX_Z_MAP_SLOTS]; | |
121 | ||
122 | static unsigned short good_blocks_table[MAX_GOOD_BLOCKS]; | |
123 | static int used_good_blocks = 0; | |
124 | static unsigned long req_nr_inodes = 0; | |
125 | ||
126 | #define bitop(name,op) \ | |
127 | static inline int name(char * addr,unsigned int nr) \ | |
128 | { \ | |
129 | int __res; \ | |
130 | __asm__ __volatile__("bt" op " %1,%2; adcl $0,%0" \ | |
131 | :"=g" (__res) \ | |
132 | :"r" (nr),"m" (*(addr)),"0" (0)); \ | |
133 | return __res; \ | |
134 | } | |
135 | ||
136 | bitop(bit,"") | |
137 | bitop(setbit,"s") | |
138 | bitop(clrbit,"r") | |
139 | ||
140 | #define inode_in_use(x) (bit(inode_map,(x))) | |
141 | #define zone_in_use(x) (bit(zone_map,(x)-FIRSTZONE+1)) | |
142 | ||
143 | #define mark_inode(x) (setbit(inode_map,(x))) | |
144 | #define unmark_inode(x) (clrbit(inode_map,(x))) | |
145 | ||
146 | #define mark_zone(x) (setbit(zone_map,(x)-FIRSTZONE+1)) | |
147 | #define unmark_zone(x) (clrbit(zone_map,(x)-FIRSTZONE+1)) | |
148 | ||
149 | /* | |
150 | * Volatile to let gcc know that this doesn't return. When trying | |
151 | * to compile this under minix, volatile gives a warning, as | |
152 | * exit() isn't defined as volatile under minix. | |
153 | */ | |
154 | volatile void fatal_error(const char * fmt_string,int status) | |
155 | { | |
156 | fprintf(stderr,fmt_string,program_name,device_name); | |
157 | exit(status); | |
158 | } | |
159 | ||
160 | #define usage() fatal_error("Usage: %s [-c | -l filename] [-nXX] [-iXX] /dev/name blocks\n",16) | |
161 | #define die(str) fatal_error("%s: " str "\n",8) | |
162 | ||
163 | /* | |
164 | * Check to make certain that our new filesystem won't be created on | |
165 | * an already mounted partition. Code adapted from mke2fs, Copyright | |
166 | * (C) 1994 Theodore Ts'o. Also licensed under GPL. | |
167 | */ | |
168 | static void check_mount(void) | |
169 | { | |
170 | FILE * f; | |
171 | struct mntent * mnt; | |
172 | ||
173 | if ((f = setmntent (MOUNTED, "r")) == NULL) | |
174 | return; | |
175 | while ((mnt = getmntent (f)) != NULL) | |
176 | if (strcmp (device_name, mnt->mnt_fsname) == 0) | |
177 | break; | |
178 | endmntent (f); | |
179 | if (!mnt) | |
180 | return; | |
181 | ||
182 | die("%s is mounted; will not make a filesystem here!"); | |
183 | } | |
184 | ||
185 | void write_tables(void) | |
186 | { | |
187 | /* Mark the super block valid. */ | |
188 | Super.s_state |= MINIX_VALID_FS; | |
189 | Super.s_state &= ~MINIX_ERROR_FS; | |
190 | ||
726f69e2 KZ |
191 | if (lseek(DEV, 0, SEEK_SET)) |
192 | die("seek to boot block failed in write_tables"); | |
193 | if (512 != write(DEV, boot_block_buffer, 512)) | |
194 | die("unable to clear boot sector"); | |
6dbe3af9 KZ |
195 | if (BLOCK_SIZE != lseek(DEV, BLOCK_SIZE, SEEK_SET)) |
196 | die("seek failed in write_tables"); | |
197 | if (BLOCK_SIZE != write(DEV, super_block_buffer, BLOCK_SIZE)) | |
198 | die("unable to write super-block"); | |
199 | if (IMAPS*BLOCK_SIZE != write(DEV,inode_map,IMAPS*BLOCK_SIZE)) | |
726f69e2 | 200 | die("unable to write inode map"); |
6dbe3af9 | 201 | if (ZMAPS*BLOCK_SIZE != write(DEV,zone_map,ZMAPS*BLOCK_SIZE)) |
726f69e2 | 202 | die("unable to write zone map"); |
6dbe3af9 | 203 | if (INODE_BUFFER_SIZE != write(DEV,inode_buffer,INODE_BUFFER_SIZE)) |
726f69e2 KZ |
204 | die("unable to write inodes"); |
205 | ||
6dbe3af9 KZ |
206 | } |
207 | ||
208 | void write_block(int blk, char * buffer) | |
209 | { | |
210 | if (blk*BLOCK_SIZE != lseek(DEV, blk*BLOCK_SIZE, SEEK_SET)) | |
211 | die("seek failed in write_block"); | |
212 | if (BLOCK_SIZE != write(DEV, buffer, BLOCK_SIZE)) | |
213 | die("write failed in write_block"); | |
214 | } | |
215 | ||
216 | int get_free_block(void) | |
217 | { | |
218 | int blk; | |
219 | ||
220 | if (used_good_blocks+1 >= MAX_GOOD_BLOCKS) | |
221 | die("too many bad blocks"); | |
222 | if (used_good_blocks) | |
223 | blk = good_blocks_table[used_good_blocks-1]+1; | |
224 | else | |
225 | blk = FIRSTZONE; | |
226 | while (blk < ZONES && zone_in_use(blk)) | |
227 | blk++; | |
228 | if (blk >= ZONES) | |
229 | die("not enough good blocks"); | |
230 | good_blocks_table[used_good_blocks] = blk; | |
231 | used_good_blocks++; | |
232 | return blk; | |
233 | } | |
234 | ||
235 | void mark_good_blocks(void) | |
236 | { | |
237 | int blk; | |
238 | ||
239 | for (blk=0 ; blk < used_good_blocks ; blk++) | |
240 | mark_zone(good_blocks_table[blk]); | |
241 | } | |
242 | ||
243 | inline int next(int zone) | |
244 | { | |
245 | if (!zone) | |
246 | zone = FIRSTZONE-1; | |
247 | while (++zone < ZONES) | |
248 | if (zone_in_use(zone)) | |
249 | return zone; | |
250 | return 0; | |
251 | } | |
252 | ||
253 | void make_bad_inode(void) | |
254 | { | |
255 | struct minix_inode * inode = &Inode[MINIX_BAD_INO]; | |
256 | int i,j,zone; | |
257 | int ind=0,dind=0; | |
258 | unsigned short ind_block[BLOCK_SIZE>>1]; | |
259 | unsigned short dind_block[BLOCK_SIZE>>1]; | |
260 | ||
261 | #define NEXT_BAD (zone = next(zone)) | |
262 | ||
263 | if (!badblocks) | |
264 | return; | |
265 | mark_inode(MINIX_BAD_INO); | |
266 | inode->i_nlinks = 1; | |
267 | inode->i_time = time(NULL); | |
268 | inode->i_mode = S_IFREG + 0000; | |
269 | inode->i_size = badblocks*BLOCK_SIZE; | |
270 | zone = next(0); | |
271 | for (i=0 ; i<7 ; i++) { | |
272 | inode->i_zone[i] = zone; | |
273 | if (!NEXT_BAD) | |
274 | goto end_bad; | |
275 | } | |
276 | inode->i_zone[7] = ind = get_free_block(); | |
277 | memset(ind_block,0,BLOCK_SIZE); | |
278 | for (i=0 ; i<512 ; i++) { | |
279 | ind_block[i] = zone; | |
280 | if (!NEXT_BAD) | |
281 | goto end_bad; | |
282 | } | |
283 | inode->i_zone[8] = dind = get_free_block(); | |
284 | memset(dind_block,0,BLOCK_SIZE); | |
285 | for (i=0 ; i<512 ; i++) { | |
286 | write_block(ind,(char *) ind_block); | |
287 | dind_block[i] = ind = get_free_block(); | |
288 | memset(ind_block,0,BLOCK_SIZE); | |
289 | for (j=0 ; j<512 ; j++) { | |
290 | ind_block[j] = zone; | |
291 | if (!NEXT_BAD) | |
292 | goto end_bad; | |
293 | } | |
294 | } | |
295 | die("too many bad blocks"); | |
296 | end_bad: | |
297 | if (ind) | |
298 | write_block(ind, (char *) ind_block); | |
299 | if (dind) | |
300 | write_block(dind, (char *) dind_block); | |
301 | } | |
302 | ||
303 | void make_root_inode(void) | |
304 | { | |
305 | struct minix_inode * inode = &Inode[MINIX_ROOT_INO]; | |
306 | ||
307 | mark_inode(MINIX_ROOT_INO); | |
308 | inode->i_zone[0] = get_free_block(); | |
309 | inode->i_nlinks = 2; | |
310 | inode->i_time = time(NULL); | |
311 | if (badblocks) | |
312 | inode->i_size = 3*dirsize; | |
313 | else { | |
314 | root_block[2*dirsize] = '\0'; | |
315 | root_block[2*dirsize+1] = '\0'; | |
316 | inode->i_size = 2*dirsize; | |
317 | } | |
318 | inode->i_mode = S_IFDIR + 0755; | |
319 | write_block(inode->i_zone[0],root_block); | |
320 | } | |
321 | ||
322 | void setup_tables(void) | |
323 | { | |
324 | int i; | |
325 | ||
326 | memset(inode_map,0xff,sizeof(inode_map)); | |
327 | memset(zone_map,0xff,sizeof(zone_map)); | |
328 | memset(super_block_buffer,0,BLOCK_SIZE); | |
726f69e2 | 329 | memset(boot_block_buffer,0,512); |
6dbe3af9 KZ |
330 | MAGIC = magic; |
331 | ZONESIZE = 0; | |
332 | MAXSIZE = (7+512+512*512)*1024; | |
333 | ZONES = BLOCKS; | |
334 | /* some magic nrs: 1 inode / 3 blocks */ | |
335 | if ( req_nr_inodes == 0 ) | |
336 | INODES = BLOCKS/3; | |
337 | else | |
338 | INODES = req_nr_inodes; | |
339 | /* I don't want some off-by-one errors, so this hack... */ | |
340 | if ((INODES & 8191) > 8188) | |
341 | INODES -= 5; | |
342 | if ((INODES & 8191) < 10) | |
343 | INODES -= 20; | |
344 | IMAPS = UPPER(INODES,BITS_PER_BLOCK); | |
345 | ZMAPS = 0; | |
346 | while (ZMAPS != UPPER(BLOCKS - NORM_FIRSTZONE,BITS_PER_BLOCK)) | |
347 | ZMAPS = UPPER(BLOCKS - NORM_FIRSTZONE,BITS_PER_BLOCK); | |
348 | FIRSTZONE = NORM_FIRSTZONE; | |
349 | for (i = FIRSTZONE ; i<ZONES ; i++) | |
350 | unmark_zone(i); | |
351 | for (i = MINIX_ROOT_INO ; i<INODES ; i++) | |
352 | unmark_inode(i); | |
353 | inode_buffer = malloc(INODE_BUFFER_SIZE); | |
354 | if (!inode_buffer) | |
726f69e2 | 355 | die("unable to allocate buffer for inodes"); |
6dbe3af9 KZ |
356 | memset(inode_buffer,0,INODE_BUFFER_SIZE); |
357 | printf("%d inodes\n",INODES); | |
358 | printf("%d blocks\n",ZONES); | |
359 | printf("Firstdatazone=%d (%d)\n",FIRSTZONE,NORM_FIRSTZONE); | |
360 | printf("Zonesize=%d\n",BLOCK_SIZE<<ZONESIZE); | |
361 | printf("Maxsize=%d\n\n",MAXSIZE); | |
362 | } | |
363 | ||
364 | /* | |
365 | * Perform a test of a block; return the number of | |
366 | * blocks readable/writeable. | |
367 | */ | |
368 | long do_check(char * buffer, int try, unsigned int current_block) | |
369 | { | |
370 | long got; | |
371 | ||
372 | /* Seek to the correct loc. */ | |
373 | if (lseek(DEV, current_block * BLOCK_SIZE, SEEK_SET) != | |
374 | current_block * BLOCK_SIZE ) { | |
375 | die("seek failed during testing of blocks"); | |
376 | } | |
377 | ||
378 | ||
379 | /* Try the read */ | |
380 | got = read(DEV, buffer, try * BLOCK_SIZE); | |
381 | if (got < 0) got = 0; | |
382 | if (got & (BLOCK_SIZE - 1 )) { | |
383 | printf("Weird values in do_check: probably bugs\n"); | |
384 | } | |
385 | got /= BLOCK_SIZE; | |
386 | return got; | |
387 | } | |
388 | ||
389 | static unsigned int currently_testing = 0; | |
390 | ||
391 | void alarm_intr(int alnum) | |
392 | { | |
393 | if (currently_testing >= ZONES) | |
394 | return; | |
395 | signal(SIGALRM,alarm_intr); | |
396 | alarm(5); | |
397 | if (!currently_testing) | |
398 | return; | |
399 | printf("%d ...", currently_testing); | |
400 | fflush(stdout); | |
401 | } | |
402 | ||
403 | void check_blocks(void) | |
404 | { | |
405 | int try,got; | |
406 | static char buffer[BLOCK_SIZE * TEST_BUFFER_BLOCKS]; | |
407 | ||
408 | currently_testing=0; | |
409 | signal(SIGALRM,alarm_intr); | |
410 | alarm(5); | |
411 | while (currently_testing < ZONES) { | |
412 | if (lseek(DEV,currently_testing*BLOCK_SIZE,SEEK_SET) != | |
413 | currently_testing*BLOCK_SIZE) | |
414 | die("seek failed in check_blocks"); | |
415 | try = TEST_BUFFER_BLOCKS; | |
416 | if (currently_testing + try > ZONES) | |
417 | try = ZONES-currently_testing; | |
418 | got = do_check(buffer, try, currently_testing); | |
419 | currently_testing += got; | |
420 | if (got == try) | |
421 | continue; | |
422 | if (currently_testing < FIRSTZONE) | |
423 | die("bad blocks before data-area: cannot make fs"); | |
424 | mark_zone(currently_testing); | |
425 | badblocks++; | |
426 | currently_testing++; | |
427 | } | |
428 | if (badblocks) | |
429 | printf("%d bad block%s\n",badblocks,(badblocks>1)?"s":""); | |
430 | } | |
431 | ||
432 | void get_list_blocks(filename) | |
433 | char *filename; | |
434 | { | |
435 | FILE *listfile; | |
436 | unsigned long blockno; | |
437 | ||
438 | listfile=fopen(filename,"r"); | |
439 | if(listfile == (FILE *)NULL) { | |
726f69e2 | 440 | die("can't open file of bad blocks"); |
6dbe3af9 KZ |
441 | } |
442 | while(!feof(listfile)) { | |
443 | fscanf(listfile,"%d\n", &blockno); | |
444 | mark_zone(blockno); | |
445 | badblocks++; | |
446 | } | |
447 | if(badblocks) { | |
448 | printf("%d bad block%s\n", badblocks, (badblocks>1)?"s":""); | |
449 | } | |
450 | } | |
451 | ||
452 | int main(int argc, char ** argv) | |
453 | { | |
454 | int i; | |
455 | char * tmp; | |
456 | struct stat statbuf; | |
457 | char * listfile = NULL; | |
458 | ||
459 | if (argc && *argv) | |
460 | program_name = *argv; | |
461 | if (INODE_SIZE * MINIX_INODES_PER_BLOCK != BLOCK_SIZE) | |
462 | die("bad inode size"); | |
463 | while (argc-- > 1) { | |
464 | argv++; | |
465 | if (argv[0][0] != '-') | |
466 | if (device_name) { | |
467 | BLOCKS = strtol(argv[0],&tmp,0); | |
468 | if (*tmp) { | |
469 | printf("strtol error: number of" | |
470 | " blocks not specified"); | |
471 | usage(); | |
472 | } | |
473 | } else | |
474 | device_name = argv[0]; | |
475 | else { | |
476 | if(argv[0][1] == 'l') { | |
477 | listfile = argv[1]; | |
478 | argv++; | |
479 | if (!(argc--)) | |
480 | usage(); | |
481 | } else { | |
482 | if(argv[0][1] == 'i') { | |
483 | req_nr_inodes | |
484 | = (unsigned long)atol(argv[1]); | |
485 | argv++; | |
486 | if (!(argc--)) | |
487 | usage(); | |
488 | } else while (*(++argv[0])) { | |
489 | switch (argv[0][0]) { | |
490 | case 'c': check=1; break; | |
491 | case 'n': | |
492 | i = strtoul(argv[0]+1,&tmp,0); | |
493 | if (*tmp) | |
494 | usage(); | |
495 | argv[0][1] = '\0'; | |
496 | if (i == 14) | |
497 | magic = MINIX_SUPER_MAGIC; | |
498 | else if (i == 30) | |
499 | magic = MINIX_SUPER_MAGIC2; | |
500 | else | |
501 | usage(); | |
502 | namelen = i; | |
503 | dirsize = i+2; | |
504 | break; | |
505 | default: usage(); | |
506 | } | |
507 | } | |
508 | } | |
509 | } | |
510 | } | |
511 | if (!device_name || BLOCKS<10 || BLOCKS > 65536) { | |
512 | usage(); | |
513 | } | |
514 | check_mount(); /* is it already mounted? */ | |
515 | tmp = root_block; | |
516 | tmp[0] = 1; | |
517 | tmp[1] = 0; | |
518 | strcpy(tmp+2,"."); | |
519 | tmp += dirsize; | |
520 | tmp[0] = 1; | |
521 | tmp[1] = 0; | |
522 | strcpy(tmp+2,".."); | |
523 | tmp += dirsize; | |
524 | tmp[0] = 2; | |
525 | tmp[1] = 0; | |
526 | strcpy(tmp+2,".badblocks"); | |
527 | DEV = open(device_name,O_RDWR ); | |
528 | if (DEV<0) | |
529 | die("unable to open %s"); | |
530 | if (fstat(DEV,&statbuf)<0) | |
531 | die("unable to stat %s"); | |
532 | if (!S_ISBLK(statbuf.st_mode)) | |
533 | check=0; | |
534 | else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) | |
726f69e2 | 535 | die("will not try to make filesystem on '%s'"); |
6dbe3af9 KZ |
536 | setup_tables(); |
537 | if (check) | |
538 | check_blocks(); | |
539 | else if (listfile) | |
540 | get_list_blocks(listfile); | |
541 | make_root_inode(); | |
542 | make_bad_inode(); | |
543 | mark_good_blocks(); | |
544 | write_tables(); | |
545 | return 0; | |
546 | } |