]> git.ipfire.org Git - thirdparty/e2fsprogs.git/blame - misc/mke2fs.c
Merge branch 'maint' into next
[thirdparty/e2fsprogs.git] / misc / mke2fs.c
CommitLineData
3839e657
TT
1/*
2 * mke2fs.c - Make a ext2fs filesystem.
efc6f628 3 *
55f4cbd9
TT
4 * Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
5 * 2003, 2004, 2005 by Theodore Ts'o.
19c78dc0
TT
6 *
7 * %Begin-Header%
8 * This file may be redistributed under the terms of the GNU Public
9 * License.
10 * %End-Header%
3839e657
TT
11 */
12
13/* Usage: mke2fs [options] device
efc6f628 14 *
3839e657 15 * The device may be a block device or a image of one, but this isn't
efc6f628 16 * enforced (but it's not much fun on a character device :-).
3839e657
TT
17 */
18
bbccc6f3 19#define _XOPEN_SOURCE 600 /* for inclusion of PATH_MAX */
ebabf2ad 20
d1154eb4 21#include "config.h"
a418d3ad 22#include <stdio.h>
3839e657 23#include <string.h>
d0c53774 24#include <strings.h>
3839e657 25#include <ctype.h>
3839e657 26#include <time.h>
756df353 27#ifdef __linux__
2740156b 28#include <sys/utsname.h>
ceec1709 29#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
2740156b 30#endif
a418d3ad 31#ifdef HAVE_GETOPT_H
3839e657 32#include <getopt.h>
373b8337
TT
33#else
34extern char *optarg;
35extern int optind;
a418d3ad
TT
36#endif
37#ifdef HAVE_UNISTD_H
3839e657 38#include <unistd.h>
a418d3ad
TT
39#endif
40#ifdef HAVE_STDLIB_H
3839e657 41#include <stdlib.h>
a418d3ad
TT
42#endif
43#ifdef HAVE_ERRNO_H
44#include <errno.h>
45#endif
0a3d8041 46#ifdef HAVE_SYS_IOCTL_H
3839e657 47#include <sys/ioctl.h>
0a3d8041 48#endif
b626b39a 49#include <libgen.h>
36585791 50#include <limits.h>
9ed8e5fe 51#include <blkid/blkid.h>
f3db3566 52
54c637d4 53#include "ext2fs/ext2_fs.h"
95fd65bb 54#include "ext2fs/ext2fsP.h"
1e3472c5 55#include "uuid/uuid.h"
63985320 56#include "util.h"
99ceb8ec
TT
57#include "support/nls-enable.h"
58#include "support/plausible.h"
1dc16b0b
TT
59#include "support/profile.h"
60#include "support/prof_err.h"
3839e657 61#include "../version.h"
f34af41b 62#include "support/quotaio.h"
23a1b987 63#include "mke2fs.h"
217c0bdf 64#include "create_inode.h"
3839e657
TT
65
66#define STRIDE_LENGTH 8
67
493024ea
TT
68#define MAX_32_NUM ((((unsigned long long) 1) << 32) - 1)
69
6733c2fd 70#ifndef __sparc__
1e3472c5
TT
71#define ZAP_BOOTBLOCK
72#endif
73
7d9e3165
LC
74#define DISCARD_STEP_MB (2048)
75
3839e657 76extern int isatty(int);
f3db3566 77extern FILE *fpopen(const char *cmd, const char *mode);
3839e657 78
23a1b987 79const char * program_name = "mke2fs";
f404167d 80static const char * device_name /* = NULL */;
3839e657
TT
81
82/* Command line options */
f404167d 83static int cflag;
23a1b987
TT
84int verbose;
85int quiet;
f404167d
TT
86static int super_only;
87static int discard = 1; /* attempt to discard device before fs creation */
88static int direct_io;
89static int force;
90static int noaction;
65c6c3e0 91static int num_backups = 2; /* number of backup bg's for sparse_super2 */
f404167d
TT
92static uid_t root_uid;
93static gid_t root_gid;
16ed5b3a
TT
94int journal_size;
95int journal_flags;
f404167d 96static int lazy_itable_init;
3c6e91c5 97static int packed_meta_blocks;
f404167d
TT
98static char *bad_blocks_filename = NULL;
99static __u32 fs_stride;
2d2d799c
LX
100/* Initialize usr/grp quotas by default */
101static unsigned int quotatype_bits = (QUOTA_USR_BIT | QUOTA_GRP_BIT);
88ee023b 102static __u64 offset;
b818205f 103static blk64_t journal_location = ~0LL;
f83f4132 104static int proceed_delay = -1;
a11ccebd 105static blk64_t dev_size;
f404167d
TT
106
107static struct ext2_super_block fs_param;
e1f71006 108static __u32 zero_buf[4];
f404167d
TT
109static char *fs_uuid = NULL;
110static char *creator_os;
111static char *volume_label;
112static char *mount_dir;
16ed5b3a 113char *journal_device;
f404167d 114static int sync_kludge; /* Set using the MKE2FS_SYNC env. option */
23a1b987 115char **fs_types;
0f267471 116const char *src_root_dir; /* Copy files from the specified directory */
2d291b3c 117static char *undo_file;
3839e657 118
105cdfe5
AS
119static int android_sparse_file; /* -E android_sparse */
120static char *android_sparse_params;
121
f404167d 122static profile_t profile;
9dc6ad1e 123
f404167d 124static int sys_page_size = 4096;
31e29a12 125
cd32129d
DW
126static int errors_behavior = 0;
127
63985320 128static void usage(void)
3839e657 129{
bdd80f28 130 fprintf(stderr, _("Usage: %s [-c|-l filename] [-b block-size] "
28e2cb9e 131 "[-C cluster-size]\n\t[-i bytes-per-inode] [-I inode-size] "
bdd80f28 132 "[-J journal-options]\n"
217c0bdf
RY
133 "\t[-G flex-group-size] [-N number-of-inodes] "
134 "[-d root-directory]\n"
9ba40002
TT
135 "\t[-m reserved-blocks-percentage] [-o creator-os]\n"
136 "\t[-g blocks-per-group] [-L volume-label] "
067911ae 137 "[-M last-mounted-directory]\n\t[-O feature[,...]] "
bdd80f28 138 "[-r fs-revision] [-E extended-option[,...]]\n"
cd32129d 139 "\t[-t fs-type] [-T usage-type ] [-U UUID] [-e errors_behavior]"
2d291b3c 140 "[-z undo_file]\n"
a195e862 141 "\t[-jnqvDFSV] device [blocks-count]\n"),
3839e657
TT
142 program_name);
143 exit(1);
144}
145
02d6f47e 146static int int_log2(unsigned long long arg)
3839e657
TT
147{
148 int l = 0;
149
150 arg >>= 1;
151 while (arg) {
152 l++;
153 arg >>= 1;
154 }
155 return l;
156}
157
23a1b987 158int int_log10(unsigned long long arg)
1dde43f0
TT
159{
160 int l;
161
162 for (l=0; arg ; l++)
163 arg = arg / 10;
164 return l;
165}
166
1d6fd6d0 167#ifdef __linux__
d99225ec
TT
168static int parse_version_number(const char *s)
169{
170 int major, minor, rev;
171 char *endptr;
172 const char *cp = s;
173
174 if (!s)
175 return 0;
176 major = strtol(cp, &endptr, 10);
177 if (cp == endptr || *endptr != '.')
178 return 0;
179 cp = endptr + 1;
180 minor = strtol(cp, &endptr, 10);
181 if (cp == endptr || *endptr != '.')
182 return 0;
183 cp = endptr + 1;
184 rev = strtol(cp, &endptr, 10);
185 if (cp == endptr)
186 return 0;
84593c2a
DW
187 return KERNEL_VERSION(major, minor, rev);
188}
189
d27a559c
LC
190static int is_before_linux_ver(unsigned int major, unsigned int minor,
191 unsigned int rev)
84593c2a
DW
192{
193 struct utsname ut;
194 static int linux_version_code = -1;
195
196 if (uname(&ut)) {
197 perror("uname");
198 exit(1);
199 }
200 if (linux_version_code < 0)
201 linux_version_code = parse_version_number(ut.release);
202 if (linux_version_code == 0)
203 return 0;
204
4e222d9b 205 return linux_version_code < (int) KERNEL_VERSION(major, minor, rev);
84593c2a
DW
206}
207#else
d27a559c
LC
208static int is_before_linux_ver(unsigned int major, unsigned int minor,
209 unsigned int rev)
84593c2a
DW
210{
211 return 0;
d99225ec 212}
1d6fd6d0 213#endif
d99225ec 214
3839e657
TT
215/*
216 * Helper function for read_bb_file and test_disk
217 */
54434927 218static void invalid_block(ext2_filsys fs EXT2FS_ATTR((unused)), blk_t blk)
3839e657 219{
6693837e 220 fprintf(stderr, _("Bad block %u out of range; ignored.\n"), blk);
3839e657
TT
221 return;
222}
223
224/*
225 * Reads the bad blocks list from a file
226 */
227static void read_bb_file(ext2_filsys fs, badblocks_list *bb_list,
228 const char *bad_blocks_file)
229{
230 FILE *f;
231 errcode_t retval;
232
233 f = fopen(bad_blocks_file, "r");
234 if (!f) {
235 com_err("read_bad_blocks_file", errno,
d9c56d3c 236 _("while trying to open %s"), bad_blocks_file);
3839e657
TT
237 exit(1);
238 }
239 retval = ext2fs_read_bb_FILE(fs, f, bb_list, invalid_block);
240 fclose (f);
241 if (retval) {
45ff69ff 242 com_err("ext2fs_read_bb_FILE", retval, "%s",
d9c56d3c 243 _("while reading in list of bad blocks from file"));
3839e657
TT
244 exit(1);
245 }
246}
247
248/*
249 * Runs the badblocks program to test the disk
250 */
251static void test_disk(ext2_filsys fs, badblocks_list *bb_list)
252{
253 FILE *f;
254 errcode_t retval;
255 char buf[1024];
256
4efbac6f 257 sprintf(buf, "badblocks -b %d -X %s%s%s %llu", fs->blocksize,
3ed57c27 258 quiet ? "" : "-s ", (cflag > 1) ? "-w " : "",
4efbac6f 259 fs->device_name, ext2fs_blocks_count(fs->super)-1);
3839e657 260 if (verbose)
d9c56d3c 261 printf(_("Running command: %s\n"), buf);
3839e657
TT
262 f = popen(buf, "r");
263 if (!f) {
264 com_err("popen", errno,
f37ab68a 265 _("while trying to run '%s'"), buf);
3839e657
TT
266 exit(1);
267 }
268 retval = ext2fs_read_bb_FILE(fs, f, bb_list, invalid_block);
f3db3566 269 pclose(f);
3839e657 270 if (retval) {
45ff69ff 271 com_err("ext2fs_read_bb_FILE", retval, "%s",
d9c56d3c 272 _("while processing list of bad blocks from program"));
3839e657
TT
273 exit(1);
274 }
275}
276
277static void handle_bad_blocks(ext2_filsys fs, badblocks_list bb_list)
278{
54434927
TT
279 dgrp_t i;
280 blk_t j;
281 unsigned must_be_good;
3839e657
TT
282 blk_t blk;
283 badblocks_iterate bb_iter;
284 errcode_t retval;
f3db3566
TT
285 blk_t group_block;
286 int group;
287 int group_bad;
3839e657
TT
288
289 if (!bb_list)
290 return;
efc6f628 291
3839e657
TT
292 /*
293 * The primary superblock and group descriptors *must* be
294 * good; if not, abort.
295 */
296 must_be_good = fs->super->s_first_data_block + 1 + fs->desc_blocks;
297 for (i = fs->super->s_first_data_block; i <= must_be_good; i++) {
cbbf031b 298 if (ext2fs_badblocks_list_test(bb_list, i)) {
d9c56d3c
TT
299 fprintf(stderr, _("Block %d in primary "
300 "superblock/group descriptor area bad.\n"), i);
d0ff90d5 301 fprintf(stderr, _("Blocks %u through %u must be good "
d9c56d3c 302 "in order to build a filesystem.\n"),
3839e657 303 fs->super->s_first_data_block, must_be_good);
54434927 304 fputs(_("Aborting....\n"), stderr);
3839e657
TT
305 exit(1);
306 }
307 }
f3db3566
TT
308
309 /*
310 * See if any of the bad blocks are showing up in the backup
311 * superblocks and/or group descriptors. If so, issue a
312 * warning and adjust the block counts appropriately.
313 */
314 group_block = fs->super->s_first_data_block +
315 fs->super->s_blocks_per_group;
efc6f628 316
f3db3566 317 for (i = 1; i < fs->group_desc_count; i++) {
92bcc595 318 group_bad = 0;
f3db3566 319 for (j=0; j < fs->desc_blocks+1; j++) {
cbbf031b
TT
320 if (ext2fs_badblocks_list_test(bb_list,
321 group_block + j)) {
efc6f628 322 if (!group_bad)
f3db3566 323 fprintf(stderr,
8deb80a5 324_("Warning: the backup superblock/group descriptors at block %u contain\n"
d9c56d3c 325" bad blocks.\n\n"),
f3db3566
TT
326 group_block);
327 group_bad++;
6493f8e8 328 group = ext2fs_group_of_blk2(fs, group_block+j);
d7cca6b0 329 ext2fs_bg_free_blocks_count_set(fs, group, ext2fs_bg_free_blocks_count(fs, group) + 1);
5711ed29 330 ext2fs_group_desc_csum_set(fs, group);
4efbac6f 331 ext2fs_free_blocks_count_add(fs->super, 1);
f3db3566
TT
332 }
333 }
334 group_block += fs->super->s_blocks_per_group;
335 }
efc6f628 336
3839e657
TT
337 /*
338 * Mark all the bad blocks as used...
339 */
cbbf031b 340 retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter);
3839e657 341 if (retval) {
45ff69ff 342 com_err("ext2fs_badblocks_list_iterate_begin", retval, "%s",
d9c56d3c 343 _("while marking bad blocks as used"));
3839e657
TT
344 exit(1);
345 }
efc6f628 346 while (ext2fs_badblocks_list_iterate(bb_iter, &blk))
c6ed60cd 347 ext2fs_mark_block_bitmap2(fs->block_map, EXT2FS_B2C(fs, blk));
cbbf031b 348 ext2fs_badblocks_list_iterate_end(bb_iter);
3839e657
TT
349}
350
9309d338
DW
351static void write_reserved_inodes(ext2_filsys fs)
352{
353 errcode_t retval;
354 ext2_ino_t ino;
355 struct ext2_inode *inode;
356
bbccc6f3 357 retval = ext2fs_get_memzero(EXT2_INODE_SIZE(fs->super), &inode);
9309d338 358 if (retval) {
d7f786c8 359 com_err("inode_init", retval, _("while allocating memory"));
9309d338
DW
360 exit(1);
361 }
9309d338
DW
362
363 for (ino = 1; ino < EXT2_FIRST_INO(fs->super); ino++)
364 ext2fs_write_inode_full(fs, ino, inode,
365 EXT2_INODE_SIZE(fs->super));
366
367 ext2fs_free_mem(&inode);
368}
369
3c6e91c5
TT
370static errcode_t packed_allocate_tables(ext2_filsys fs)
371{
372 errcode_t retval;
373 dgrp_t i;
374 blk64_t goal = 0;
375
376 for (i = 0; i < fs->group_desc_count; i++) {
377 retval = ext2fs_new_block2(fs, goal, NULL, &goal);
378 if (retval)
379 return retval;
380 ext2fs_block_alloc_stats2(fs, goal, +1);
381 ext2fs_block_bitmap_loc_set(fs, i, goal);
382 }
383 for (i = 0; i < fs->group_desc_count; i++) {
384 retval = ext2fs_new_block2(fs, goal, NULL, &goal);
385 if (retval)
386 return retval;
387 ext2fs_block_alloc_stats2(fs, goal, +1);
388 ext2fs_inode_bitmap_loc_set(fs, i, goal);
389 }
390 for (i = 0; i < fs->group_desc_count; i++) {
391 blk64_t end = ext2fs_blocks_count(fs->super) - 1;
392 retval = ext2fs_get_free_blocks2(fs, goal, end,
393 fs->inode_blocks_per_group,
394 fs->block_map, &goal);
395 if (retval)
396 return retval;
397 ext2fs_block_alloc_stats_range(fs, goal,
398 fs->inode_blocks_per_group, +1);
399 ext2fs_inode_table_loc_set(fs, i, goal);
35a7a576 400 ext2fs_group_desc_csum_set(fs, i);
3c6e91c5
TT
401 }
402 return 0;
403}
404
6fcd6f84 405static void write_inode_tables(ext2_filsys fs, int lazy_flag, int itable_zeroed)
16ed5b3a
TT
406{
407 errcode_t retval;
02d6f47e 408 blk64_t blk;
54434927 409 dgrp_t i;
e1632421 410 int num;
95fd65bb 411 struct ext2fs_numeric_progress_struct progress;
16ed5b3a 412
95fd65bb
VAH
413 ext2fs_numeric_progress_init(fs, &progress,
414 _("Writing inode tables: "),
415 fs->group_desc_count);
1dde43f0 416
3839e657 417 for (i = 0; i < fs->group_desc_count; i++) {
c498cb11 418 ext2fs_numeric_progress_update(fs, &progress, i);
efc6f628 419
d7cca6b0 420 blk = ext2fs_inode_table_loc(fs, i);
19c78dc0 421 num = fs->inode_blocks_per_group;
16ed5b3a 422
e1632421
TT
423 if (lazy_flag)
424 num = ext2fs_div_ceil((fs->super->s_inodes_per_group -
425 ext2fs_bg_itable_unused(fs, i)) *
426 EXT2_INODE_SIZE(fs->super),
427 EXT2_BLOCK_SIZE(fs->super));
6fcd6f84 428 if (!lazy_flag || itable_zeroed) {
d2d22a29 429 /* The kernel doesn't need to zero the itable blocks */
e633b58a 430 ext2fs_bg_flags_set(fs, i, EXT2_BG_INODE_ZEROED);
5711ed29 431 ext2fs_group_desc_csum_set(fs, i);
19c78dc0 432 }
5effd0a0
DW
433 if (!itable_zeroed) {
434 retval = ext2fs_zero_blocks2(fs, blk, num, &blk, &num);
435 if (retval) {
436 fprintf(stderr, _("\nCould not write %d "
437 "blocks in inode table starting at %llu: %s\n"),
438 num, blk, error_message(retval));
439 exit(1);
440 }
0f2794c0 441 }
7d5633cf
TT
442 if (sync_kludge) {
443 if (sync_kludge == 1)
fbfe1561 444 io_channel_flush(fs->io);
7d5633cf 445 else if ((i % sync_kludge) == 0)
fbfe1561 446 io_channel_flush(fs->io);
7d5633cf 447 }
3839e657 448 }
95fd65bb
VAH
449 ext2fs_numeric_progress_close(fs, &progress,
450 _("done \n"));
9309d338
DW
451
452 /* Reserved inodes must always have correct checksums */
c0495d96 453 if (ext2fs_has_feature_metadata_csum(fs->super))
9309d338 454 write_reserved_inodes(fs);
3839e657
TT
455}
456
457static void create_root_dir(ext2_filsys fs)
458{
5113a6e3 459 errcode_t retval;
f3db3566 460 struct ext2_inode inode;
3839e657
TT
461
462 retval = ext2fs_mkdir(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, 0);
463 if (retval) {
45ff69ff
AD
464 com_err("ext2fs_mkdir", retval, "%s",
465 _("while creating root dir"));
3839e657
TT
466 exit(1);
467 }
dc9cc700 468 if (root_uid != 0 || root_gid != 0) {
f3db3566
TT
469 retval = ext2fs_read_inode(fs, EXT2_ROOT_INO, &inode);
470 if (retval) {
45ff69ff 471 com_err("ext2fs_read_inode", retval, "%s",
d9c56d3c 472 _("while reading root inode"));
f3db3566
TT
473 exit(1);
474 }
dc9cc700
AD
475
476 inode.i_uid = root_uid;
477 ext2fs_set_i_uid_high(inode, root_uid >> 16);
478 inode.i_gid = root_gid;
479 ext2fs_set_i_gid_high(inode, root_gid >> 16);
480
e27b4563 481 retval = ext2fs_write_new_inode(fs, EXT2_ROOT_INO, &inode);
f3db3566 482 if (retval) {
45ff69ff 483 com_err("ext2fs_write_inode", retval, "%s",
d9c56d3c 484 _("while setting root inode ownership"));
f3db3566
TT
485 exit(1);
486 }
487 }
3839e657
TT
488}
489
490static void create_lost_and_found(ext2_filsys fs)
491{
2d328bb7 492 unsigned int lpf_size = 0;
3839e657 493 errcode_t retval;
dfcdc32f 494 ext2_ino_t ino;
3839e657
TT
495 const char *name = "lost+found";
496 int i;
497
6a525069 498 fs->umask = 077;
3839e657
TT
499 retval = ext2fs_mkdir(fs, EXT2_ROOT_INO, 0, name);
500 if (retval) {
45ff69ff 501 com_err("ext2fs_mkdir", retval, "%s",
d9c56d3c 502 _("while creating /lost+found"));
3839e657
TT
503 exit(1);
504 }
505
506 retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name, strlen(name), 0, &ino);
507 if (retval) {
45ff69ff 508 com_err("ext2_lookup", retval, "%s",
d9c56d3c 509 _("while looking up /lost+found"));
3839e657
TT
510 exit(1);
511 }
efc6f628 512
3839e657 513 for (i=1; i < EXT2_NDIR_BLOCKS; i++) {
8c7c6eb1
AD
514 /* Ensure that lost+found is at least 2 blocks, so we always
515 * test large empty blocks for big-block filesystems. */
516 if ((lpf_size += fs->blocksize) >= 16*1024 &&
517 lpf_size >= 2 * fs->blocksize)
50787ea2 518 break;
3839e657
TT
519 retval = ext2fs_expand_dir(fs, ino);
520 if (retval) {
45ff69ff 521 com_err("ext2fs_expand_dir", retval, "%s",
d9c56d3c 522 _("while expanding /lost+found"));
3839e657
TT
523 exit(1);
524 }
6a525069 525 }
3839e657
TT
526}
527
528static void create_bad_block_inode(ext2_filsys fs, badblocks_list bb_list)
529{
530 errcode_t retval;
efc6f628 531
463e7327 532 ext2fs_mark_inode_bitmap2(fs->inode_map, EXT2_BAD_INO);
5711ed29 533 ext2fs_inode_alloc_stats2(fs, EXT2_BAD_INO, +1, 0);
3839e657
TT
534 retval = ext2fs_update_bb_inode(fs, bb_list);
535 if (retval) {
45ff69ff 536 com_err("ext2fs_update_bb_inode", retval, "%s",
d9c56d3c 537 _("while setting bad block inode"));
3839e657
TT
538 exit(1);
539 }
540
541}
542
543static void reserve_inodes(ext2_filsys fs)
544{
dfcdc32f 545 ext2_ino_t i;
3839e657 546
5711ed29
TT
547 for (i = EXT2_ROOT_INO + 1; i < EXT2_FIRST_INODE(fs->super); i++)
548 ext2fs_inode_alloc_stats2(fs, i, +1, 0);
3839e657
TT
549 ext2fs_mark_ib_dirty(fs);
550}
551
756df353 552#define BSD_DISKMAGIC (0x82564557UL) /* The disk magic number */
7ef3bb83 553#define BSD_MAGICDISK (0x57455682UL) /* The disk magic number reversed */
756df353 554#define BSD_LABEL_OFFSET 64
756df353 555
04a96857 556static void zap_sector(ext2_filsys fs, int sect, int nsect)
f3db3566 557{
3f85f65c 558 char *buf;
f3db3566 559 int retval;
756df353 560 unsigned int *magic;
f3db3566 561
105cdfe5 562 buf = calloc(512, nsect);
568101f7 563 if (!buf) {
4ea7bd04
TT
564 printf(_("Out of memory erasing sectors %d-%d\n"),
565 sect, sect + nsect - 1);
568101f7
AD
566 exit(1);
567 }
756df353 568
7ef3bb83
TT
569 if (sect == 0) {
570 /* Check for a BSD disklabel, and don't erase it if so */
24a117ab 571 retval = io_channel_read_blk64(fs->io, 0, -512, buf);
7ef3bb83
TT
572 if (retval)
573 fprintf(stderr,
574 _("Warning: could not read block 0: %s\n"),
575 error_message(retval));
576 else {
577 magic = (unsigned int *) (buf + BSD_LABEL_OFFSET);
578 if ((*magic == BSD_DISKMAGIC) ||
579 (*magic == BSD_MAGICDISK))
580 return;
581 }
756df353 582 }
756df353 583
7098810d 584 memset(buf, 0, 512*nsect);
e41784eb 585 io_channel_set_blksize(fs->io, 512);
24a117ab 586 retval = io_channel_write_blk64(fs->io, sect, -512*nsect, buf);
e41784eb 587 io_channel_set_blksize(fs->io, fs->blocksize);
3f85f65c 588 free(buf);
f3db3566 589 if (retval)
6693837e
TT
590 fprintf(stderr, _("Warning: could not erase sector %d: %s\n"),
591 sect, error_message(retval));
f3db3566 592}
16ed5b3a
TT
593
594static void create_journal_dev(ext2_filsys fs)
595{
95fd65bb 596 struct ext2fs_numeric_progress_struct progress;
16ed5b3a
TT
597 errcode_t retval;
598 char *buf;
02d6f47e 599 blk64_t blk, err_blk;
b626b39a 600 int c, count, err_count;
16ed5b3a 601
d6a27e00 602 retval = ext2fs_create_journal_superblock(fs,
4efbac6f 603 ext2fs_blocks_count(fs->super), 0, &buf);
d6a27e00 604 if (retval) {
45ff69ff 605 com_err("create_journal_dev", retval, "%s",
d6a27e00
TT
606 _("while initializing journal superblock"));
607 exit(1);
608 }
6c54689f
AD
609
610 if (journal_flags & EXT2_MKJOURNAL_LAZYINIT)
611 goto write_superblock;
612
95fd65bb
VAH
613 ext2fs_numeric_progress_init(fs, &progress,
614 _("Zeroing journal device: "),
615 ext2fs_blocks_count(fs->super));
b626b39a 616 blk = 0;
4efbac6f 617 count = ext2fs_blocks_count(fs->super);
b626b39a
AK
618 while (count > 0) {
619 if (count > 1024)
620 c = 1024;
621 else
622 c = count;
02d6f47e 623 retval = ext2fs_zero_blocks2(fs, blk, c, &err_blk, &err_count);
b626b39a
AK
624 if (retval) {
625 com_err("create_journal_dev", retval,
626 _("while zeroing journal device "
02d6f47e 627 "(block %llu, count %d)"),
b626b39a
AK
628 err_blk, err_count);
629 exit(1);
630 }
631 blk += c;
632 count -= c;
c498cb11 633 ext2fs_numeric_progress_update(fs, &progress, blk);
16ed5b3a 634 }
dc2ec525 635
6c54689f
AD
636 ext2fs_numeric_progress_close(fs, &progress, NULL);
637write_superblock:
24a117ab
VAH
638 retval = io_channel_write_blk64(fs->io,
639 fs->super->s_first_data_block+1,
640 1, buf);
a54733d2 641 (void) ext2fs_free_mem(&buf);
16ed5b3a 642 if (retval) {
45ff69ff 643 com_err("create_journal_dev", retval, "%s",
16ed5b3a
TT
644 _("while writing journal superblock"));
645 exit(1);
646 }
16ed5b3a 647}
f3db3566 648
3839e657
TT
649static void show_stats(ext2_filsys fs)
650{
ef9abe5f 651 struct ext2_super_block *s = fs->super;
1e3472c5 652 char buf[80];
63253946 653 char *os;
02d6f47e 654 blk64_t group_block;
54434927
TT
655 dgrp_t i;
656 int need, col_left;
efc6f628 657
6d82e1f4
TT
658 if (!verbose) {
659 printf(_("Creating filesystem with %llu %dk blocks and "
660 "%u inodes\n"),
661 ext2fs_blocks_count(s), fs->blocksize >> 10,
662 s->s_inodes_count);
663 goto skip_details;
664 }
665
4efbac6f
VAH
666 if (ext2fs_blocks_count(&fs_param) != ext2fs_blocks_count(s))
667 fprintf(stderr, _("warning: %llu blocks unused.\n\n"),
668 ext2fs_blocks_count(&fs_param) - ext2fs_blocks_count(s));
50787ea2
TT
669
670 memset(buf, 0, sizeof(buf));
671 strncpy(buf, s->s_volume_name, sizeof(s->s_volume_name));
d9c56d3c 672 printf(_("Filesystem label=%s\n"), buf);
74e1211b
TT
673 os = e2p_os2string(fs->super->s_creator_os);
674 if (os)
675 printf(_("OS type: %s\n"), os);
63253946 676 free(os);
d9c56d3c 677 printf(_("Block size=%u (log=%u)\n"), fs->blocksize,
50787ea2 678 s->s_log_block_size);
7889640d 679 if (ext2fs_has_feature_bigalloc(fs->super))
412376ef 680 printf(_("Cluster size=%u (log=%u)\n"),
1da5ef70
TT
681 fs->blocksize << fs->cluster_ratio_bits,
682 s->s_log_cluster_size);
412376ef 683 else
1da5ef70 684 printf(_("Fragment size=%u (log=%u)\n"), EXT2_CLUSTER_SIZE(s),
412376ef 685 s->s_log_cluster_size);
9ed8e5fe
ES
686 printf(_("Stride=%u blocks, Stripe width=%u blocks\n"),
687 s->s_raid_stride, s->s_raid_stripe_width);
4efbac6f
VAH
688 printf(_("%u inodes, %llu blocks\n"), s->s_inodes_count,
689 ext2fs_blocks_count(s));
690 printf(_("%llu blocks (%2.2f%%) reserved for the super user\n"),
691 ext2fs_r_blocks_count(s),
692 100.0 * ext2fs_r_blocks_count(s) / ext2fs_blocks_count(s));
d9c56d3c 693 printf(_("First data block=%u\n"), s->s_first_data_block);
dc9cc700
AD
694 if (root_uid != 0 || root_gid != 0)
695 printf(_("Root directory owner=%u:%u\n"), root_uid, root_gid);
d323f8fb
TT
696 if (s->s_reserved_gdt_blocks)
697 printf(_("Maximum filesystem blocks=%lu\n"),
698 (s->s_reserved_gdt_blocks + fs->desc_blocks) *
f2de1d38 699 EXT2_DESC_PER_BLOCK(s) * s->s_blocks_per_group);
d9c56d3c 700 if (fs->group_desc_count > 1)
c8c071a0 701 printf(_("%u block groups\n"), fs->group_desc_count);
d9c56d3c 702 else
c8c071a0 703 printf(_("%u block group\n"), fs->group_desc_count);
7889640d 704 if (ext2fs_has_feature_bigalloc(fs->super))
412376ef
TT
705 printf(_("%u blocks per group, %u clusters per group\n"),
706 s->s_blocks_per_group, s->s_clusters_per_group);
707 else
708 printf(_("%u blocks per group, %u fragments per group\n"),
709 s->s_blocks_per_group, s->s_clusters_per_group);
d9c56d3c 710 printf(_("%u inodes per group\n"), s->s_inodes_per_group);
3839e657 711
6d82e1f4 712skip_details:
3839e657
TT
713 if (fs->group_desc_count == 1) {
714 printf("\n");
715 return;
716 }
d323f8fb 717
6d82e1f4
TT
718 if (!e2p_is_null_uuid(s->s_uuid))
719 printf(_("Filesystem UUID: %s\n"), e2p_uuid2str(s->s_uuid));
45ff69ff 720 printf("%s", _("Superblock backups stored on blocks: "));
3839e657
TT
721 group_block = s->s_first_data_block;
722 col_left = 0;
723 for (i = 1; i < fs->group_desc_count; i++) {
724 group_block += s->s_blocks_per_group;
521e3685
TT
725 if (!ext2fs_bg_has_super(fs, i))
726 continue;
7671433a
TT
727 if (i != 1)
728 printf(", ");
6733c2fd 729 need = int_log10(group_block) + 2;
1dde43f0 730 if (need > col_left) {
3839e657 731 printf("\n\t");
1dde43f0 732 col_left = 72;
3839e657 733 }
1dde43f0 734 col_left -= need;
02d6f47e 735 printf("%llu", group_block);
3839e657
TT
736 }
737 printf("\n\n");
738}
739
48b35e23
TT
740/*
741 * Returns true if making a file system for the Hurd, else 0
742 */
743static int for_hurd(const char *os)
744{
745 if (!os) {
746#ifdef __GNU__
747 return 1;
748#else
749 return 0;
750#endif
751 }
752 if (isdigit(*os))
753 return (atoi(os) == EXT2_OS_HURD);
754 return (strcasecmp(os, "GNU") == 0 || strcasecmp(os, "hurd") == 0);
755}
756
1e3472c5
TT
757/*
758 * Set the S_CREATOR_OS field. Return true if OS is known,
759 * otherwise, 0.
760 */
761static int set_os(struct ext2_super_block *sb, char *os)
762{
763 if (isdigit (*os))
764 sb->s_creator_os = atoi (os);
765 else if (strcasecmp(os, "linux") == 0)
766 sb->s_creator_os = EXT2_OS_LINUX;
767 else if (strcasecmp(os, "GNU") == 0 || strcasecmp(os, "hurd") == 0)
768 sb->s_creator_os = EXT2_OS_HURD;
ea1e8f47
TT
769 else if (strcasecmp(os, "freebsd") == 0)
770 sb->s_creator_os = EXT2_OS_FREEBSD;
771 else if (strcasecmp(os, "lites") == 0)
772 sb->s_creator_os = EXT2_OS_LITES;
1e3472c5
TT
773 else
774 return 0;
775 return 1;
776}
777
a418d3ad
TT
778#define PATH_SET "PATH=/sbin"
779
efc6f628 780static void parse_extended_opts(struct ext2_super_block *param,
c6a44136 781 const char *opts)
a29f4d30 782{
2d328bb7 783 char *buf, *token, *next, *p, *arg, *badopt = 0;
a29f4d30 784 int len;
d323f8fb 785 int r_usage = 0;
2d2d799c 786 int ret;
a29f4d30
TT
787
788 len = strlen(opts);
789 buf = malloc(len+1);
790 if (!buf) {
45ff69ff 791 fprintf(stderr, "%s",
d323f8fb 792 _("Couldn't allocate memory to parse options!\n"));
a29f4d30
TT
793 exit(1);
794 }
795 strcpy(buf, opts);
796 for (token = buf; token && *token; token = next) {
797 p = strchr(token, ',');
798 next = 0;
799 if (p) {
800 *p = 0;
801 next = p+1;
d323f8fb 802 }
a29f4d30
TT
803 arg = strchr(token, '=');
804 if (arg) {
805 *arg = 0;
806 arg++;
807 }
2bc30417
AD
808 if (strcmp(token, "desc-size") == 0 ||
809 strcmp(token, "desc_size") == 0) {
810 int desc_size;
811
7889640d 812 if (!ext2fs_has_feature_64bit(&fs_param)) {
2bc30417
AD
813 fprintf(stderr,
814 _("%s requires '-O 64bit'\n"), token);
815 r_usage++;
816 continue;
817 }
818 if (param->s_reserved_gdt_blocks != 0) {
819 fprintf(stderr,
820 _("'%s' must be before 'resize=%u'\n"),
821 token, param->s_reserved_gdt_blocks);
822 r_usage++;
823 continue;
824 }
825 if (!arg) {
826 r_usage++;
827 badopt = token;
828 continue;
829 }
830 desc_size = strtoul(arg, &p, 0);
831 if (*p || (desc_size & (desc_size - 1))) {
832 fprintf(stderr,
833 _("Invalid desc_size: '%s'\n"), arg);
834 r_usage++;
835 continue;
836 }
837 param->s_desc_size = desc_size;
e1f71006
JQ
838 } else if (strcmp(token, "hash_seed") == 0) {
839 if (!arg) {
840 r_usage++;
841 badopt = token;
842 continue;
843 }
844 if (uuid_parse(arg,
845 (unsigned char *)param->s_hash_seed) != 0) {
846 fprintf(stderr,
847 _("Invalid hash seed: %s\n"), arg);
848 r_usage++;
849 continue;
850 }
88ee023b
TT
851 } else if (strcmp(token, "offset") == 0) {
852 if (!arg) {
853 r_usage++;
854 badopt = token;
855 continue;
856 }
857 offset = strtoull(arg, &p, 0);
858 if (*p) {
859 fprintf(stderr, _("Invalid offset: %s\n"),
860 arg);
861 r_usage++;
862 continue;
863 }
2bc30417 864 } else if (strcmp(token, "mmp_update_interval") == 0) {
0f5eba75
AD
865 if (!arg) {
866 r_usage++;
867 badopt = token;
868 continue;
869 }
870 param->s_mmp_update_interval = strtoul(arg, &p, 0);
871 if (*p) {
872 fprintf(stderr,
873 _("Invalid mmp_update_interval: %s\n"),
874 arg);
875 r_usage++;
876 continue;
877 }
65c6c3e0
TT
878 } else if (strcmp(token, "num_backup_sb") == 0) {
879 if (!arg) {
880 r_usage++;
881 badopt = token;
882 continue;
883 }
884 num_backups = strtoul(arg, &p, 0);
885 if (*p || num_backups > 2) {
886 fprintf(stderr,
887 _("Invalid # of backup "
35a0bdd7 888 "superblocks: %s\n"),
65c6c3e0
TT
889 arg);
890 r_usage++;
891 continue;
892 }
3c6e91c5
TT
893 } else if (strcmp(token, "packed_meta_blocks") == 0) {
894 if (arg)
895 packed_meta_blocks = strtoul(arg, &p, 0);
896 else
897 packed_meta_blocks = 1;
898 if (packed_meta_blocks)
899 journal_location = 0;
0f5eba75 900 } else if (strcmp(token, "stride") == 0) {
a29f4d30 901 if (!arg) {
d323f8fb 902 r_usage++;
0c17cb25 903 badopt = token;
a29f4d30
TT
904 continue;
905 }
0c17cb25 906 param->s_raid_stride = strtoul(arg, &p, 0);
5b734a0e 907 if (*p) {
d9c56d3c 908 fprintf(stderr,
f37ab68a
TT
909 _("Invalid stride parameter: %s\n"),
910 arg);
d323f8fb
TT
911 r_usage++;
912 continue;
913 }
0c17cb25
TT
914 } else if (strcmp(token, "stripe-width") == 0 ||
915 strcmp(token, "stripe_width") == 0) {
916 if (!arg) {
917 r_usage++;
918 badopt = token;
919 continue;
920 }
921 param->s_raid_stripe_width = strtoul(arg, &p, 0);
5b734a0e 922 if (*p) {
0c17cb25
TT
923 fprintf(stderr,
924 _("Invalid stripe-width parameter: %s\n"),
925 arg);
926 r_usage++;
927 continue;
928 }
d323f8fb 929 } else if (!strcmp(token, "resize")) {
02d6f47e
JS
930 blk64_t resize;
931 unsigned long bpg, rsv_groups;
c6a44136
TT
932 unsigned long group_desc_count, desc_blocks;
933 unsigned int gdpb, blocksize;
934 int rsv_gdb;
d323f8fb
TT
935
936 if (!arg) {
937 r_usage++;
0c17cb25 938 badopt = token;
a29f4d30
TT
939 continue;
940 }
d323f8fb 941
02d6f47e
JS
942 resize = parse_num_blocks2(arg,
943 param->s_log_block_size);
d323f8fb
TT
944
945 if (resize == 0) {
efc6f628 946 fprintf(stderr,
55f4cbd9
TT
947 _("Invalid resize parameter: %s\n"),
948 arg);
d323f8fb
TT
949 r_usage++;
950 continue;
951 }
4efbac6f 952 if (resize <= ext2fs_blocks_count(param)) {
45ff69ff 953 fprintf(stderr, "%s",
f37ab68a
TT
954 _("The resize maximum must be greater "
955 "than the filesystem size.\n"));
c6a44136
TT
956 r_usage++;
957 continue;
958 }
d323f8fb 959
c6a44136
TT
960 blocksize = EXT2_BLOCK_SIZE(param);
961 bpg = param->s_blocks_per_group;
962 if (!bpg)
963 bpg = blocksize * 8;
f2de1d38 964 gdpb = EXT2_DESC_PER_BLOCK(param);
4efbac6f
VAH
965 group_desc_count = (__u32) ext2fs_div64_ceil(
966 ext2fs_blocks_count(param), bpg);
c6a44136
TT
967 desc_blocks = (group_desc_count +
968 gdpb - 1) / gdpb;
02d6f47e 969 rsv_groups = ext2fs_div64_ceil(resize, bpg);
efc6f628 970 rsv_gdb = ext2fs_div_ceil(rsv_groups, gdpb) -
c6a44136 971 desc_blocks;
9b9a780f 972 if (rsv_gdb > (int) EXT2_ADDR_PER_BLOCK(param))
c6a44136
TT
973 rsv_gdb = EXT2_ADDR_PER_BLOCK(param);
974
975 if (rsv_gdb > 0) {
b290d2dc 976 if (param->s_rev_level == EXT2_GOOD_OLD_REV) {
45ff69ff 977 fprintf(stderr, "%s",
b290d2dc 978 _("On-line resizing not supported with revision 0 filesystems\n"));
21400381 979 free(buf);
b290d2dc
TT
980 exit(1);
981 }
7889640d 982 ext2fs_set_feature_resize_inode(param);
c6a44136
TT
983
984 param->s_reserved_gdt_blocks = rsv_gdb;
985 }
6cb27404
TT
986 } else if (!strcmp(token, "test_fs")) {
987 param->s_flags |= EXT2_FLAGS_TEST_FILESYS;
a4396e9d 988 } else if (!strcmp(token, "lazy_itable_init")) {
43781b94
TT
989 if (arg)
990 lazy_itable_init = strtoul(arg, &p, 0);
991 else
992 lazy_itable_init = 1;
6c54689f
AD
993 } else if (!strcmp(token, "lazy_journal_init")) {
994 if (arg)
995 journal_flags |= strtoul(arg, &p, 0) ?
996 EXT2_MKJOURNAL_LAZYINIT : 0;
997 else
998 journal_flags |= EXT2_MKJOURNAL_LAZYINIT;
dc9cc700
AD
999 } else if (!strcmp(token, "root_owner")) {
1000 if (arg) {
1001 root_uid = strtoul(arg, &p, 0);
1002 if (*p != ':') {
1003 fprintf(stderr,
1004 _("Invalid root_owner: '%s'\n"),
1005 arg);
1006 r_usage++;
1007 continue;
1008 }
1009 p++;
1010 root_gid = strtoul(p, &p, 0);
1011 if (*p) {
1012 fprintf(stderr,
1013 _("Invalid root_owner: '%s'\n"),
1014 arg);
1015 r_usage++;
1016 continue;
1017 }
1018 } else {
1019 root_uid = getuid();
1020 root_gid = getgid();
1021 }
0bc85dfb
LC
1022 } else if (!strcmp(token, "discard")) {
1023 discard = 1;
1024 } else if (!strcmp(token, "nodiscard")) {
1025 discard = 0;
d678fef0 1026 } else if (!strcmp(token, "quotatype")) {
a195e862
TT
1027 char *errtok = NULL;
1028
d678fef0
AK
1029 if (!arg) {
1030 r_usage++;
1031 badopt = token;
1032 continue;
1033 }
a195e862
TT
1034 quotatype_bits = 0;
1035 ret = parse_quota_types(arg, &quotatype_bits, &errtok);
2d2d799c 1036 if (ret) {
051fd4e0 1037 if (errtok) {
a195e862
TT
1038 fprintf(stderr,
1039 "Failed to parse quota type at %s", errtok);
051fd4e0
TT
1040 free(errtok);
1041 } else
a195e862
TT
1042 com_err(program_name, ret,
1043 "while parsing quota type");
d678fef0 1044 r_usage++;
a195e862 1045 badopt = token;
d678fef0
AK
1046 continue;
1047 }
105cdfe5
AS
1048 } else if (!strcmp(token, "android_sparse")) {
1049 android_sparse_file = 1;
0c17cb25 1050 } else {
d323f8fb 1051 r_usage++;
0c17cb25
TT
1052 badopt = token;
1053 }
a29f4d30 1054 }
d323f8fb 1055 if (r_usage) {
0c17cb25 1056 fprintf(stderr, _("\nBad option(s) specified: %s\n\n"
bb145b01 1057 "Extended options are separated by commas, "
a29f4d30
TT
1058 "and may take an argument which\n"
1059 "\tis set off by an equals ('=') sign.\n\n"
bb145b01 1060 "Valid extended options are:\n"
88ee023b 1061 "\tmmp_update_interval=<interval>\n"
65c6c3e0 1062 "\tnum_backup_sb=<0|1|2>\n"
0c17cb25
TT
1063 "\tstride=<RAID per-disk data chunk in blocks>\n"
1064 "\tstripe-width=<RAID stride * data disks in blocks>\n"
88ee023b 1065 "\toffset=<offset to create the file system>\n"
a4396e9d 1066 "\tresize=<resize maximum size in blocks>\n"
3c6e91c5 1067 "\tpacked_meta_blocks=<0 to disable, 1 to enable>\n"
a4396e9d 1068 "\tlazy_itable_init=<0 to disable, 1 to enable>\n"
6c54689f 1069 "\tlazy_journal_init=<0 to disable, 1 to enable>\n"
a195e862 1070 "\troot_owner=<uid of root dir>:<gid of root dir>\n"
0bc85dfb
LC
1071 "\ttest_fs\n"
1072 "\tdiscard\n"
d678fef0 1073 "\tnodiscard\n"
a195e862 1074 "\tquotatype=<quota type(s) to be enabled>\n\n"),
2d328bb7 1075 badopt ? badopt : "");
21400381 1076 free(buf);
a29f4d30
TT
1077 exit(1);
1078 }
0c17cb25
TT
1079 if (param->s_raid_stride &&
1080 (param->s_raid_stripe_width % param->s_raid_stride) != 0)
1081 fprintf(stderr, _("\nWarning: RAID stripe-width %u not an even "
1082 "multiple of stride %u.\n\n"),
1083 param->s_raid_stripe_width, param->s_raid_stride);
1084
21400381 1085 free(buf);
efc6f628 1086}
a29f4d30 1087
896938d5 1088static __u32 ok_features[3] = {
558df544 1089 /* Compat */
843049c4 1090 EXT3_FEATURE_COMPAT_HAS_JOURNAL |
d323f8fb 1091 EXT2_FEATURE_COMPAT_RESIZE_INODE |
f5fa2007 1092 EXT2_FEATURE_COMPAT_DIR_INDEX |
65c6c3e0
TT
1093 EXT2_FEATURE_COMPAT_EXT_ATTR |
1094 EXT4_FEATURE_COMPAT_SPARSE_SUPER2,
558df544
TT
1095 /* Incompat */
1096 EXT2_FEATURE_INCOMPAT_FILETYPE|
bf6b848e 1097 EXT3_FEATURE_INCOMPAT_EXTENTS|
c046ac7f 1098 EXT3_FEATURE_INCOMPAT_JOURNAL_DEV|
c2d4300b 1099 EXT2_FEATURE_INCOMPAT_META_BG|
02d6f47e 1100 EXT4_FEATURE_INCOMPAT_FLEX_BG|
6a081f6d 1101 EXT4_FEATURE_INCOMPAT_EA_INODE|
0f5eba75 1102 EXT4_FEATURE_INCOMPAT_MMP |
b451c8dd 1103 EXT4_FEATURE_INCOMPAT_64BIT|
bbb85949 1104 EXT4_FEATURE_INCOMPAT_INLINE_DATA|
1b7623b8 1105 EXT4_FEATURE_INCOMPAT_ENCRYPT |
3f0cf647
AB
1106 EXT4_FEATURE_INCOMPAT_CSUM_SEED |
1107 EXT4_FEATURE_INCOMPAT_LARGEDIR,
558df544
TT
1108 /* R/O compat */
1109 EXT2_FEATURE_RO_COMPAT_LARGE_FILE|
2be8fe43
TT
1110 EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
1111 EXT4_FEATURE_RO_COMPAT_DIR_NLINK|
1112 EXT4_FEATURE_RO_COMPAT_EXTRA_ISIZE|
d2d22a29 1113 EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER|
c6ed60cd 1114 EXT4_FEATURE_RO_COMPAT_GDT_CSUM|
1f5d7a89 1115 EXT4_FEATURE_RO_COMPAT_BIGALLOC|
7becb206 1116 EXT4_FEATURE_RO_COMPAT_QUOTA|
0c18d036
LX
1117 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM|
1118 EXT4_FEATURE_RO_COMPAT_PROJECT
896938d5 1119};
a29f4d30
TT
1120
1121
9dc6ad1e
TT
1122static void syntax_err_report(const char *filename, long err, int line_num)
1123{
efc6f628 1124 fprintf(stderr,
9dc6ad1e
TT
1125 _("Syntax error in mke2fs config file (%s, line #%d)\n\t%s\n"),
1126 filename, line_num, error_message(err));
1127 exit(1);
1128}
1129
abcfdfda 1130static const char *config_fn[] = { ROOT_SYSCONFDIR "/mke2fs.conf", 0 };
9dc6ad1e 1131
efc6f628 1132static void edit_feature(const char *str, __u32 *compat_array)
9dc6ad1e
TT
1133{
1134 if (!str)
1135 return;
1136
1137 if (e2p_edit_feature(str, compat_array, ok_features)) {
efc6f628 1138 fprintf(stderr, _("Invalid filesystem option set: %s\n"),
9dc6ad1e
TT
1139 str);
1140 exit(1);
1141 }
1142}
1143
6a426c97
ES
1144static void edit_mntopts(const char *str, __u32 *mntopts)
1145{
1146 if (!str)
1147 return;
1148
1149 if (e2p_edit_mntopts(str, mntopts, ~0)) {
1150 fprintf(stderr, _("Invalid mount option set: %s\n"),
1151 str);
1152 exit(1);
1153 }
1154}
1155
3d43836f
TT
1156struct str_list {
1157 char **list;
1158 int num;
1159 int max;
1160};
1161
1162static errcode_t init_list(struct str_list *sl)
1163{
1164 sl->num = 0;
a54733d2 1165 sl->max = 1;
3d43836f
TT
1166 sl->list = malloc((sl->max+1) * sizeof(char *));
1167 if (!sl->list)
1168 return ENOMEM;
1169 sl->list[0] = 0;
1170 return 0;
1171}
1172
1173static errcode_t push_string(struct str_list *sl, const char *str)
1174{
1175 char **new_list;
1176
1177 if (sl->num >= sl->max) {
1178 sl->max += 2;
1179 new_list = realloc(sl->list, (sl->max+1) * sizeof(char *));
1180 if (!new_list)
1181 return ENOMEM;
1182 sl->list = new_list;
1183 }
1184 sl->list[sl->num] = malloc(strlen(str)+1);
1185 if (sl->list[sl->num] == 0)
1186 return ENOMEM;
1187 strcpy(sl->list[sl->num], str);
1188 sl->num++;
1189 sl->list[sl->num] = 0;
1190 return 0;
1191}
1192
1193static void print_str_list(char **list)
1194{
1195 char **cpp;
1196
1197 for (cpp = list; *cpp; cpp++) {
1198 printf("'%s'", *cpp);
1199 if (cpp[1])
1200 fputs(", ", stdout);
1201 }
1202 fputc('\n', stdout);
1203}
1204
2ee4544d
TT
1205/*
1206 * Return TRUE if the profile has the given subsection
1207 */
577c773a 1208static int profile_has_subsection(profile_t prof, const char *section,
2ee4544d
TT
1209 const char *subsection)
1210{
1211 void *state;
1212 const char *names[4];
1213 char *name;
1214 int ret = 0;
1215
1216 names[0] = section;
1217 names[1] = subsection;
1218 names[2] = 0;
1219
577c773a 1220 if (profile_iterator_create(prof, names,
2ee4544d
TT
1221 PROFILE_ITER_LIST_SECTION |
1222 PROFILE_ITER_RELATIONS_ONLY, &state))
1223 return 0;
1224
1225 if ((profile_iterator(&state, &name, 0) == 0) && name) {
1226 free(name);
1227 ret = 1;
1228 }
1229
1230 profile_iterator_free(&state);
1231 return ret;
1232}
1233
3d43836f
TT
1234static char **parse_fs_type(const char *fs_type,
1235 const char *usage_types,
577c773a 1236 struct ext2_super_block *sb,
493024ea 1237 blk64_t fs_blocks_count,
3d43836f
TT
1238 char *progname)
1239{
1240 const char *ext_type = 0;
1241 char *parse_str;
1242 char *profile_type = 0;
1243 char *cp, *t;
1244 const char *size_type;
1245 struct str_list list;
493024ea 1246 unsigned long long meg;
48b35e23 1247 int is_hurd = for_hurd(creator_os);
3d43836f
TT
1248
1249 if (init_list(&list))
1250 return 0;
1251
1252 if (fs_type)
1253 ext_type = fs_type;
7f5601e5
TT
1254 else if (is_hurd)
1255 ext_type = "ext2";
1a71bd42
TT
1256 else if (!strcmp(program_name, "mke3fs"))
1257 ext_type = "ext3";
237b7b23
ES
1258 else if (!strcmp(program_name, "mke4fs"))
1259 ext_type = "ext4";
3d43836f
TT
1260 else if (progname) {
1261 ext_type = strrchr(progname, '/');
1262 if (ext_type)
1263 ext_type++;
1264 else
1265 ext_type = progname;
1266
1267 if (!strncmp(ext_type, "mkfs.", 5)) {
1268 ext_type += 5;
1269 if (ext_type[0] == 0)
1270 ext_type = 0;
1271 } else
1272 ext_type = 0;
1273 }
1274
1275 if (!ext_type) {
1276 profile_get_string(profile, "defaults", "fs_type", 0,
1277 "ext2", &profile_type);
1278 ext_type = profile_type;
1279 if (!strcmp(ext_type, "ext2") && (journal_size != 0))
1280 ext_type = "ext3";
1281 }
1282
2ee4544d
TT
1283
1284 if (!profile_has_subsection(profile, "fs_types", ext_type) &&
1285 strcmp(ext_type, "ext2")) {
1286 printf(_("\nYour mke2fs.conf file does not define the "
1287 "%s filesystem type.\n"), ext_type);
1288 if (!strcmp(ext_type, "ext3") || !strcmp(ext_type, "ext4") ||
1289 !strcmp(ext_type, "ext4dev")) {
45ff69ff
AD
1290 printf("%s", _("You probably need to install an "
1291 "updated mke2fs.conf file.\n\n"));
2ee4544d
TT
1292 }
1293 if (!force) {
45ff69ff 1294 printf("%s", _("Aborting...\n"));
2ee4544d 1295 exit(1);
bad89b2a
TT
1296 }
1297 }
1298
577c773a 1299 meg = (1024 * 1024) / EXT2_BLOCK_SIZE(sb);
493024ea 1300 if (fs_blocks_count < 3 * meg)
3d43836f 1301 size_type = "floppy";
493024ea 1302 else if (fs_blocks_count < 512 * meg)
3d43836f 1303 size_type = "small";
22d8ce51
NK
1304 else if (fs_blocks_count < 4 * 1024 * 1024 * meg)
1305 size_type = "default";
1306 else if (fs_blocks_count < 16 * 1024 * 1024 * meg)
493024ea 1307 size_type = "big";
3d43836f 1308 else
22d8ce51 1309 size_type = "huge";
3d43836f
TT
1310
1311 if (!usage_types)
1312 usage_types = size_type;
1313
4d5cf8b1 1314 parse_str = malloc(strlen(usage_types)+1);
3d43836f 1315 if (!parse_str) {
80a1806d 1316 free(profile_type);
3d43836f
TT
1317 free(list.list);
1318 return 0;
1319 }
4d5cf8b1 1320 strcpy(parse_str, usage_types);
3d43836f
TT
1321
1322 if (ext_type)
1323 push_string(&list, ext_type);
1324 cp = parse_str;
1325 while (1) {
1326 t = strchr(cp, ',');
1327 if (t)
1328 *t = '\0';
1329
2ee4544d 1330 if (*cp) {
0f7479b3
TT
1331 if (profile_has_subsection(profile, "fs_types", cp))
1332 push_string(&list, cp);
1333 else if (strcmp(cp, "default") != 0)
2ee4544d
TT
1334 fprintf(stderr,
1335 _("\nWarning: the fs_type %s is not "
0f7479b3 1336 "defined in mke2fs.conf\n\n"),
2ee4544d 1337 cp);
2ee4544d 1338 }
3d43836f
TT
1339 if (t)
1340 cp = t+1;
577c773a 1341 else
3d43836f 1342 break;
3d43836f
TT
1343 }
1344 free(parse_str);
45e338f5 1345 free(profile_type);
7f5601e5
TT
1346 if (is_hurd)
1347 push_string(&list, "hurd");
3d43836f
TT
1348 return (list.list);
1349}
1350
23a1b987 1351char *get_string_from_profile(char **types, const char *opt,
3d43836f
TT
1352 const char *def_val)
1353{
1354 char *ret = 0;
3d43836f
TT
1355 int i;
1356
577c773a 1357 for (i=0; types[i]; i++);
3d43836f 1358 for (i-=1; i >=0 ; i--) {
577c773a 1359 profile_get_string(profile, "fs_types", types[i],
3d43836f
TT
1360 opt, 0, &ret);
1361 if (ret)
1362 return ret;
1363 }
1364 profile_get_string(profile, "defaults", opt, 0, def_val, &ret);
1365 return (ret);
1366}
1367
23a1b987 1368int get_int_from_profile(char **types, const char *opt, int def_val)
3d43836f
TT
1369{
1370 int ret;
1371 char **cpp;
1372
1373 profile_get_integer(profile, "defaults", opt, 0, def_val, &ret);
577c773a 1374 for (cpp = types; *cpp; cpp++)
3d43836f
TT
1375 profile_get_integer(profile, "fs_types", *cpp, opt, ret, &ret);
1376 return ret;
1377}
1378
d0de4c95
AF
1379static unsigned int get_uint_from_profile(char **types, const char *opt,
1380 unsigned int def_val)
1381{
1382 unsigned int ret;
1383 char **cpp;
1384
1385 profile_get_uint(profile, "defaults", opt, 0, def_val, &ret);
1386 for (cpp = types; *cpp; cpp++)
1387 profile_get_uint(profile, "fs_types", *cpp, opt, ret, &ret);
1388 return ret;
1389}
1390
577c773a 1391static double get_double_from_profile(char **types, const char *opt,
d3859af3
AK
1392 double def_val)
1393{
1394 double ret;
1395 char **cpp;
1396
1397 profile_get_double(profile, "defaults", opt, 0, def_val, &ret);
577c773a 1398 for (cpp = types; *cpp; cpp++)
d3859af3
AK
1399 profile_get_double(profile, "fs_types", *cpp, opt, ret, &ret);
1400 return ret;
1401}
1402
23a1b987 1403int get_bool_from_profile(char **types, const char *opt, int def_val)
a4396e9d
TT
1404{
1405 int ret;
1406 char **cpp;
1407
1408 profile_get_boolean(profile, "defaults", opt, 0, def_val, &ret);
577c773a 1409 for (cpp = types; *cpp; cpp++)
a4396e9d
TT
1410 profile_get_boolean(profile, "fs_types", *cpp, opt, ret, &ret);
1411 return ret;
1412}
3d43836f 1413
d48bc604
TT
1414extern const char *mke2fs_default_profile;
1415static const char *default_files[] = { "<default>", 0 };
1416
9ed8e5fe
ES
1417#ifdef HAVE_BLKID_PROBE_GET_TOPOLOGY
1418/*
1419 * Sets the geometry of a device (stripe/stride), and returns the
1420 * device's alignment offset, if any, or a negative error.
1421 */
1599b470 1422static int get_device_geometry(const char *file,
4e222d9b
TT
1423 struct ext2_super_block *param,
1424 unsigned int psector_size)
9ed8e5fe
ES
1425{
1426 int rc = -1;
4e222d9b 1427 unsigned int blocksize;
9ed8e5fe
ES
1428 blkid_probe pr;
1429 blkid_topology tp;
1430 unsigned long min_io;
1431 unsigned long opt_io;
13b0b123
ES
1432 struct stat statbuf;
1433
1434 /* Nothing to do for a regular file */
1435 if (!stat(file, &statbuf) && S_ISREG(statbuf.st_mode))
1436 return 0;
9ed8e5fe
ES
1437
1438 pr = blkid_new_probe_from_filename(file);
1439 if (!pr)
1440 goto out;
1441
1442 tp = blkid_probe_get_topology(pr);
1443 if (!tp)
1444 goto out;
1445
1446 min_io = blkid_topology_get_minimum_io_size(tp);
1447 opt_io = blkid_topology_get_optimal_io_size(tp);
4e222d9b 1448 blocksize = EXT2_BLOCK_SIZE(param);
1599b470
TT
1449 if ((min_io == 0) && (psector_size > blocksize))
1450 min_io = psector_size;
1451 if ((opt_io == 0) && min_io)
1452 opt_io = min_io;
1453 if ((opt_io == 0) && (psector_size > blocksize))
1454 opt_io = psector_size;
9ed8e5fe 1455
d568782a
ES
1456 /* setting stripe/stride to blocksize is pointless */
1457 if (min_io > blocksize)
4e222d9b 1458 param->s_raid_stride = min_io / blocksize;
d568782a 1459 if (opt_io > blocksize)
4e222d9b 1460 param->s_raid_stripe_width = opt_io / blocksize;
9ed8e5fe
ES
1461
1462 rc = blkid_topology_get_alignment_offset(tp);
1463out:
1464 blkid_free_probe(pr);
1465 return rc;
1466}
1467#endif
1468
3839e657
TT
1469static void PRS(int argc, char *argv[])
1470{
dbcd6178 1471 int b, c, flags;
2d34a25f 1472 int cluster_size = 0;
79e62409 1473 char *tmp, **cpp;
87d9b2fb 1474 int explicit_fssize = 0;
4a600566
TT
1475 int blocksize = 0;
1476 int inode_ratio = 0;
932a489c 1477 int inode_size = 0;
9ba40002 1478 unsigned long flex_bg_size = 0;
d3859af3 1479 double reserved_ratio = -1.0;
bb1158b9 1480 int lsector_size = 0, psector_size = 0;
82739458 1481 int show_version_only = 0, is_device = 0;
de8f3a76 1482 unsigned long long num_inodes = 0; /* unsigned long long to catch too-large input */
a418d3ad 1483 errcode_t retval;
4a600566 1484 char * oldpath = getenv("PATH");
c6a44136 1485 char * extended_opts = 0;
4c2b28ab
TT
1486 char * fs_type = 0;
1487 char * usage_types = 0;
d20403df
DW
1488 /*
1489 * NOTE: A few words about fs_blocks_count and blocksize:
1490 *
1491 * Initially, blocksize is set to zero, which implies 1024.
1492 * If -b is specified, blocksize is updated to the user's value.
1493 *
1494 * Next, the device size or the user's "blocks" command line argument
1495 * is used to set fs_blocks_count; the units are blocksize.
1496 *
1497 * Later, if blocksize hasn't been set and the profile specifies a
1498 * blocksize, then blocksize is updated and fs_blocks_count is scaled
1499 * appropriately. Note the change in units!
1500 *
1501 * Finally, we complain about fs_blocks_count > 2^32 on a non-64bit fs.
1502 */
493024ea 1503 blk64_t fs_blocks_count = 0;
31e29a12 1504 long sysval;
9dc6ad1e
TT
1505 int s_opt = -1, r_opt = -1;
1506 char *fs_features = 0;
a039df9c 1507 int fs_features_size = 0;
9dc6ad1e 1508 int use_bsize;
642935c0
TT
1509 char *newpath;
1510 int pathlen = sizeof(PATH_SET) + 1;
1511
1512 if (oldpath)
1513 pathlen += strlen(oldpath);
1514 newpath = malloc(pathlen);
9ec68af7 1515 if (!newpath) {
45ff69ff
AD
1516 fprintf(stderr, "%s",
1517 _("Couldn't allocate memory for new PATH.\n"));
9ec68af7
NK
1518 exit(1);
1519 }
642935c0 1520 strcpy(newpath, PATH_SET);
14bbcbc3 1521
3839e657 1522 /* Update our PATH to include /sbin */
a418d3ad 1523 if (oldpath) {
a418d3ad
TT
1524 strcat (newpath, ":");
1525 strcat (newpath, oldpath);
642935c0
TT
1526 }
1527 putenv (newpath);
3839e657 1528
31e29a12
TT
1529 /* Determine the system page size if possible */
1530#ifdef HAVE_SYSCONF
1531#if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE))
1532#define _SC_PAGESIZE _SC_PAGE_SIZE
1533#endif
1534#ifdef _SC_PAGESIZE
1535 sysval = sysconf(_SC_PAGESIZE);
aab6fe73 1536 if (sysval > 0)
31e29a12
TT
1537 sys_page_size = sysval;
1538#endif /* _SC_PAGESIZE */
1539#endif /* HAVE_SYSCONF */
9dc6ad1e
TT
1540
1541 if ((tmp = getenv("MKE2FS_CONFIG")) != NULL)
1542 config_fn[0] = tmp;
1543 profile_set_syntax_err_cb(syntax_err_report);
d48bc604
TT
1544 retval = profile_init(config_fn, &profile);
1545 if (retval == ENOENT) {
9ec68af7
NK
1546 retval = profile_init(default_files, &profile);
1547 if (retval)
1548 goto profile_error;
1549 retval = profile_set_default(profile, mke2fs_default_profile);
1550 if (retval)
1551 goto profile_error;
1552 } else if (retval) {
1553profile_error:
1554 fprintf(stderr, _("Couldn't init profile successfully"
1555 " (error: %ld).\n"), retval);
1556 exit(1);
d48bc604 1557 }
efc6f628 1558
3839e657
TT
1559 setbuf(stdout, NULL);
1560 setbuf(stderr, NULL);
a6d8302b
TT
1561 add_error_table(&et_ext2_error_table);
1562 add_error_table(&et_prof_error_table);
9b9a780f
TT
1563 memset(&fs_param, 0, sizeof(struct ext2_super_block));
1564 fs_param.s_rev_level = 1; /* Create revision 1 filesystems now */
843049c4 1565
d27a559c 1566 if (is_before_linux_ver(2, 2, 0))
9b9a780f 1567 fs_param.s_rev_level = 0;
0072f8de
AD
1568
1569 if (argc && *argv) {
1570 program_name = get_progname(*argv);
1571
1572 /* If called as mkfs.ext3, create a journal inode */
1a71bd42
TT
1573 if (!strcmp(program_name, "mkfs.ext3") ||
1574 !strcmp(program_name, "mke3fs"))
0072f8de
AD
1575 journal_size = -1;
1576 }
1577
1e3472c5 1578 while ((c = getopt (argc, argv,
0f267471 1579 "b:cd:e:g:i:jl:m:no:qr:s:t:vC:DE:FG:I:J:KL:M:N:O:R:ST:U:Vz:")) != EOF) {
3839e657
TT
1580 switch (c) {
1581 case 'b':
86a985e7 1582 blocksize = parse_num_blocks2(optarg, -1);
c5290fae
TT
1583 b = (blocksize > 0) ? blocksize : -blocksize;
1584 if (b < EXT2_MIN_BLOCK_SIZE ||
86a985e7 1585 b > EXT2_MAX_BLOCK_SIZE) {
d9c56d3c 1586 com_err(program_name, 0,
f37ab68a 1587 _("invalid block size - %s"), optarg);
3839e657
TT
1588 exit(1);
1589 }
932a489c
AD
1590 if (blocksize > 4096)
1591 fprintf(stderr, _("Warning: blocksize %d not "
1592 "usable on most systems.\n"),
1593 blocksize);
efc6f628 1594 if (blocksize > 0)
9b9a780f 1595 fs_param.s_log_block_size =
c5290fae
TT
1596 int_log2(blocksize >>
1597 EXT2_MIN_BLOCK_LOG_SIZE);
3839e657 1598 break;
b10fd5e8 1599 case 'c': /* Check for bad blocks */
3ed57c27 1600 cflag++;
3839e657 1601 break;
c6ed60cd 1602 case 'C':
86a985e7 1603 cluster_size = parse_num_blocks2(optarg, -1);
4b20ea26 1604 if (cluster_size <= EXT2_MIN_CLUSTER_SIZE ||
86a985e7 1605 cluster_size > EXT2_MAX_CLUSTER_SIZE) {
d9c56d3c 1606 com_err(program_name, 0,
28e2cb9e 1607 _("invalid cluster size - %s"),
3839e657
TT
1608 optarg);
1609 exit(1);
1610 }
3839e657 1611 break;
0f267471
AD
1612 case 'd':
1613 src_root_dir = optarg;
1614 break;
37c8db7b
TT
1615 case 'D':
1616 direct_io = 1;
1617 break;
2a83b3c3 1618 case 'R':
45ff69ff 1619 com_err(program_name, 0, "%s",
2a83b3c3
AD
1620 _("'-R' is deprecated, use '-E' instead"));
1621 /* fallthrough */
1622 case 'E':
1623 extended_opts = optarg;
1624 break;
cd32129d
DW
1625 case 'e':
1626 if (strcmp(optarg, "continue") == 0)
1627 errors_behavior = EXT2_ERRORS_CONTINUE;
1628 else if (strcmp(optarg, "remount-ro") == 0)
1629 errors_behavior = EXT2_ERRORS_RO;
1630 else if (strcmp(optarg, "panic") == 0)
1631 errors_behavior = EXT2_ERRORS_PANIC;
1632 else {
1633 com_err(program_name, 0,
1634 _("bad error behavior - %s"),
1635 optarg);
1636 usage();
1637 }
1638 break;
2a83b3c3
AD
1639 case 'F':
1640 force++;
1641 break;
3839e657 1642 case 'g':
9b9a780f 1643 fs_param.s_blocks_per_group = strtoul(optarg, &tmp, 0);
f3db3566 1644 if (*tmp) {
45ff69ff
AD
1645 com_err(program_name, 0, "%s",
1646 _("Illegal number for blocks per group"));
f3db3566
TT
1647 exit(1);
1648 }
9b9a780f 1649 if ((fs_param.s_blocks_per_group % 8) != 0) {
45ff69ff 1650 com_err(program_name, 0, "%s",
d9c56d3c 1651 _("blocks per group must be multiple of 8"));
3839e657
TT
1652 exit(1);
1653 }
1654 break;
9ba40002
TT
1655 case 'G':
1656 flex_bg_size = strtoul(optarg, &tmp, 0);
1657 if (*tmp) {
45ff69ff 1658 com_err(program_name, 0, "%s",
9ba40002
TT
1659 _("Illegal number for flex_bg size"));
1660 exit(1);
1661 }
d531450c 1662 if (flex_bg_size < 1 ||
9ba40002 1663 (flex_bg_size & (flex_bg_size-1)) != 0) {
45ff69ff 1664 com_err(program_name, 0, "%s",
9ba40002
TT
1665 _("flex_bg size must be a power of 2"));
1666 exit(1);
1667 }
a131053e
AF
1668 if (flex_bg_size > MAX_32_NUM) {
1669 com_err(program_name, 0,
1670 _("flex_bg size (%lu) must be less than"
1671 " or equal to 2^31"), flex_bg_size);
1672 exit(1);
1673 }
9ba40002 1674 break;
3839e657 1675 case 'i':
79ffbf25 1676 inode_ratio = parse_num_blocks(optarg, -1);
932a489c 1677 if (inode_ratio < EXT2_MIN_BLOCK_SIZE ||
79ffbf25 1678 inode_ratio > EXT2_MAX_BLOCK_SIZE * 1024) {
d9c56d3c 1679 com_err(program_name, 0,
bb145b01 1680 _("invalid inode ratio %s (min %d/max %d)"),
932a489c 1681 optarg, EXT2_MIN_BLOCK_SIZE,
e447ba37 1682 EXT2_MAX_BLOCK_SIZE * 1024);
3839e657
TT
1683 exit(1);
1684 }
1685 break;
2a83b3c3
AD
1686 case 'I':
1687 inode_size = strtoul(optarg, &tmp, 0);
1688 if (*tmp) {
1689 com_err(program_name, 0,
1690 _("invalid inode size - %s"), optarg);
1691 exit(1);
1692 }
1693 break;
1694 case 'j':
1695 if (!journal_size)
1696 journal_size = -1;
1697 break;
dc2ec525
TT
1698 case 'J':
1699 parse_journal_opts(optarg);
1700 break;
5827d241 1701 case 'K':
45ff69ff
AD
1702 fprintf(stderr, "%s",
1703 _("Warning: -K option is deprecated and "
1704 "should not be used anymore. Use "
1705 "\'-E nodiscard\' extended option "
1706 "instead!\n"));
5827d241
ES
1707 discard = 0;
1708 break;
3839e657 1709 case 'l':
80a1806d
DW
1710 bad_blocks_filename = realloc(bad_blocks_filename,
1711 strlen(optarg) + 1);
f3db3566 1712 if (!bad_blocks_filename) {
45ff69ff 1713 com_err(program_name, ENOMEM, "%s",
d9c56d3c 1714 _("in malloc for bad_blocks_filename"));
f3db3566
TT
1715 exit(1);
1716 }
1717 strcpy(bad_blocks_filename, optarg);
3839e657 1718 break;
2a83b3c3
AD
1719 case 'L':
1720 volume_label = optarg;
2832fd8b
TT
1721 if (strlen(volume_label) > EXT2_LABEL_LEN) {
1722 volume_label[EXT2_LABEL_LEN] = '\0';
1723 fprintf(stderr, _("Warning: label too long; will be truncated to '%s'\n\n"),
1724 volume_label);
1725 }
2a83b3c3 1726 break;
3839e657 1727 case 'm':
ce911145 1728 reserved_ratio = strtod(optarg, &tmp);
8d822455
TT
1729 if ( *tmp || reserved_ratio > 50 ||
1730 reserved_ratio < 0) {
3839e657 1731 com_err(program_name, 0,
bb145b01 1732 _("invalid reserved blocks percent - %s"),
3839e657
TT
1733 optarg);
1734 exit(1);
1735 }
1736 break;
2a83b3c3
AD
1737 case 'M':
1738 mount_dir = optarg;
1739 break;
50787ea2
TT
1740 case 'n':
1741 noaction++;
1742 break;
2a83b3c3
AD
1743 case 'N':
1744 num_inodes = strtoul(optarg, &tmp, 0);
1745 if (*tmp) {
1746 com_err(program_name, 0,
1747 _("bad num inodes - %s"), optarg);
1748 exit(1);
1749 }
1750 break;
1e3472c5
TT
1751 case 'o':
1752 creator_os = optarg;
1753 break;
2a83b3c3 1754 case 'O':
a039df9c
TT
1755 retval = ext2fs_resize_mem(fs_features_size,
1756 fs_features_size + 1 + strlen(optarg),
1757 &fs_features);
1758 if (retval) {
1759 com_err(program_name, retval,
1760 _("while allocating fs_feature string"));
1761 exit(1);
1762 }
1763 if (fs_features_size)
1764 strcat(fs_features, ",");
1765 else
1766 fs_features[0] = 0;
1767 strcat(fs_features, optarg);
1768 fs_features_size += 1 + strlen(optarg);
2a83b3c3 1769 break;
2524785d
AD
1770 case 'q':
1771 quiet = 1;
1772 break;
7f88b043 1773 case 'r':
9dc6ad1e 1774 r_opt = strtoul(optarg, &tmp, 0);
2524785d
AD
1775 if (*tmp) {
1776 com_err(program_name, 0,
1777 _("bad revision level - %s"), optarg);
1778 exit(1);
1779 }
4b59352e
FS
1780 if (r_opt > EXT2_MAX_SUPP_REV) {
1781 com_err(program_name, EXT2_ET_REV_TOO_HIGH,
1782 _("while trying to create revision %d"), r_opt);
1783 exit(1);
1784 }
9dc6ad1e 1785 fs_param.s_rev_level = r_opt;
7f88b043 1786 break;
b10fd5e8 1787 case 's': /* deprecated */
9dc6ad1e 1788 s_opt = atoi(optarg);
521e3685 1789 break;
f3db3566
TT
1790 case 'S':
1791 super_only = 1;
1792 break;
3d43836f 1793 case 't':
9f7c3afa 1794 if (fs_type) {
45ff69ff 1795 com_err(program_name, 0, "%s",
9f7c3afa
ES
1796 _("The -t option may only be used once"));
1797 exit(1);
1798 }
4c2b28ab 1799 fs_type = strdup(optarg);
50787ea2 1800 break;
3d43836f 1801 case 'T':
9f7c3afa 1802 if (usage_types) {
45ff69ff 1803 com_err(program_name, 0, "%s",
9f7c3afa
ES
1804 _("The -T option may only be used once"));
1805 exit(1);
1806 }
4c2b28ab 1807 usage_types = strdup(optarg);
3d43836f 1808 break;
b0afdda1
TT
1809 case 'U':
1810 fs_uuid = optarg;
1811 break;
2a83b3c3
AD
1812 case 'v':
1813 verbose = 1;
1814 break;
818180cd
TT
1815 case 'V':
1816 /* Print version number and exit */
1e6e4c5e
TT
1817 show_version_only++;
1818 break;
2d291b3c
DW
1819 case 'z':
1820 undo_file = optarg;
1821 break;
3839e657
TT
1822 default:
1823 usage();
1824 }
3839e657 1825 }
55f4cbd9 1826 if ((optind == argc) && !show_version_only)
3839e657 1827 usage();
55f4cbd9 1828 device_name = argv[optind++];
a418d3ad 1829
1e6e4c5e 1830 if (!quiet || show_version_only)
efc6f628 1831 fprintf (stderr, "mke2fs %s (%s)\n", E2FSPROGS_VERSION,
3879857e
TT
1832 E2FSPROGS_DATE);
1833
1e6e4c5e 1834 if (show_version_only) {
efc6f628 1835 fprintf(stderr, _("\tUsing %s\n"),
1e6e4c5e
TT
1836 error_message(EXT2_ET_BASE));
1837 exit(0);
1838 }
1839
77dc4eb0
TT
1840 /*
1841 * If there's no blocksize specified and there is a journal
1842 * device, use it to figure out the blocksize
1843 */
c5290fae 1844 if (blocksize <= 0 && journal_device) {
77dc4eb0 1845 ext2_filsys jfs;
a7ccdff8 1846 io_manager io_ptr;
77dc4eb0 1847
a7ccdff8 1848#ifdef CONFIG_TESTIO_DEBUG
f38cf3cb
TT
1849 if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) {
1850 io_ptr = test_io_manager;
1851 test_io_backing_manager = unix_io_manager;
1852 } else
a7ccdff8 1853#endif
f38cf3cb 1854 io_ptr = unix_io_manager;
77dc4eb0
TT
1855 retval = ext2fs_open(journal_device,
1856 EXT2_FLAG_JOURNAL_DEV_OK, 0,
a7ccdff8 1857 0, io_ptr, &jfs);
77dc4eb0
TT
1858 if (retval) {
1859 com_err(program_name, retval,
1860 _("while trying to open journal device %s\n"),
1861 journal_device);
1862 exit(1);
1863 }
54434927 1864 if ((blocksize < 0) && (jfs->blocksize < (unsigned) (-blocksize))) {
c5290fae 1865 com_err(program_name, 0,
ddc32a04 1866 _("Journal dev blocksize (%d) smaller than "
c5290fae
TT
1867 "minimum blocksize %d\n"), jfs->blocksize,
1868 -blocksize);
1869 exit(1);
1870 }
77dc4eb0 1871 blocksize = jfs->blocksize;
f8df04bc 1872 printf(_("Using journal device's blocksize: %d\n"), blocksize);
9b9a780f 1873 fs_param.s_log_block_size =
77dc4eb0 1874 int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
47fee2ef 1875 ext2fs_close_free(&jfs);
77dc4eb0 1876 }
dc2ec525 1877
55f4cbd9 1878 if (optind < argc) {
493024ea
TT
1879 fs_blocks_count = parse_num_blocks2(argv[optind++],
1880 fs_param.s_log_block_size);
1881 if (!fs_blocks_count) {
792cce30 1882 com_err(program_name, 0,
9d92a201 1883 _("invalid blocks '%s' on device '%s'"),
792cce30 1884 argv[optind - 1], device_name);
55f4cbd9
TT
1885 exit(1);
1886 }
1887 }
1888 if (optind < argc)
1889 usage();
1890
fbfe1561
TT
1891 profile_get_integer(profile, "options", "sync_kludge", 0, 0,
1892 &sync_kludge);
1893 tmp = getenv("MKE2FS_SYNC");
1894 if (tmp)
1895 sync_kludge = atoi(tmp);
1896
f83f4132
TT
1897 profile_get_integer(profile, "options", "proceed_delay", 0, 0,
1898 &proceed_delay);
1899
dbcd6178
TT
1900 /* The isatty() test is so we don't break existing scripts */
1901 flags = CREATE_FILE;
87d9b2fb 1902 if (isatty(0) && isatty(1) && !offset)
dbcd6178 1903 flags |= CHECK_FS_EXIST;
a11ccebd
TT
1904 if (!quiet)
1905 flags |= VERBOSE_CREATE;
ce2e295d
TT
1906 if (fs_blocks_count == 0)
1907 flags |= NO_SIZE;
dc01088d
MH
1908 else
1909 explicit_fssize = 1;
dbcd6178 1910 if (!check_plausibility(device_name, flags, &is_device) && !force)
f83f4132 1911 proceed_question(proceed_delay);
d69f43f5 1912
63985320 1913 check_mount(device_name, force, _("filesystem"));
a418d3ad 1914
9b27e9cc 1915 /* Determine the size of the device (if possible) */
493024ea
TT
1916 if (noaction && fs_blocks_count) {
1917 dev_size = fs_blocks_count;
50787ea2 1918 retval = 0;
493024ea 1919 } else
0a3d8041 1920#ifndef _WIN32
02d6f47e
JS
1921 retval = ext2fs_get_device_size2(device_name,
1922 EXT2_BLOCK_SIZE(&fs_param),
1923 &dev_size);
0a3d8041
JQ
1924#else
1925 retval = ext2fs_get_device_size(device_name,
1926 EXT2_BLOCK_SIZE(&fs_param),
1927 &dev_size);
1928#endif
a789d840 1929 if (retval && (retval != EXT2_ET_UNIMPLEMENTED)) {
45ff69ff 1930 com_err(program_name, retval, "%s",
d9c56d3c 1931 _("while trying to determine filesystem size"));
a789d840
TT
1932 exit(1);
1933 }
493024ea 1934 if (!fs_blocks_count) {
a789d840 1935 if (retval == EXT2_ET_UNIMPLEMENTED) {
45ff69ff 1936 com_err(program_name, 0, "%s",
d9c56d3c 1937 _("Couldn't determine device size; you "
a789d840 1938 "must specify\nthe size of the "
d9c56d3c 1939 "filesystem\n"));
a418d3ad 1940 exit(1);
26ab5315
TT
1941 } else {
1942 if (dev_size == 0) {
45ff69ff 1943 com_err(program_name, 0, "%s",
26ab5315
TT
1944 _("Device size reported to be zero. "
1945 "Invalid partition specified, or\n\t"
1946 "partition table wasn't reread "
1947 "after running fdisk, due to\n\t"
1948 "a modified partition being busy "
1949 "and in use. You may need to reboot\n\t"
1950 "to re-read your partition table.\n"
1951 ));
1952 exit(1);
1953 }
493024ea
TT
1954 fs_blocks_count = dev_size;
1955 if (sys_page_size > EXT2_BLOCK_SIZE(&fs_param))
1956 fs_blocks_count &= ~((blk64_t) ((sys_page_size /
4efbac6f 1957 EXT2_BLOCK_SIZE(&fs_param))-1));
4efbac6f 1958 }
82739458 1959 } else if (!force && is_device && (fs_blocks_count > dev_size)) {
45ff69ff 1960 com_err(program_name, 0, "%s",
c5290fae 1961 _("Filesystem larger than apparent device size."));
f83f4132 1962 proceed_question(proceed_delay);
a418d3ad 1963 }
3839e657 1964
4c2b28ab
TT
1965 if (!fs_type)
1966 profile_get_string(profile, "devices", device_name,
1967 "fs_type", 0, &fs_type);
1968 if (!usage_types)
1969 profile_get_string(profile, "devices", device_name,
1970 "usage_types", 0, &usage_types);
1971
9b27e9cc
TT
1972 /*
1973 * We have the file system (or device) size, so we can now
1974 * determine the appropriate file system types so the fs can
1975 * be appropriately configured.
1976 */
1977 fs_types = parse_fs_type(fs_type, usage_types, &fs_param,
1978 fs_blocks_count ? fs_blocks_count : dev_size,
1979 argv[0]);
1980 if (!fs_types) {
45ff69ff 1981 fprintf(stderr, "%s", _("Failed to parse fs types list\n"));
9b27e9cc
TT
1982 exit(1);
1983 }
1984
1985 /* Figure out what features should be enabled */
1986
1987 tmp = NULL;
1988 if (fs_param.s_rev_level != EXT2_GOOD_OLD_REV) {
1989 tmp = get_string_from_profile(fs_types, "base_features",
c6889a64 1990 "sparse_super,large_file,filetype,resize_inode,dir_index");
9b27e9cc
TT
1991 edit_feature(tmp, &fs_param.s_feature_compat);
1992 free(tmp);
1993
6a426c97
ES
1994 /* And which mount options as well */
1995 tmp = get_string_from_profile(fs_types, "default_mntopts",
1996 "acl,user_xattr");
1997 edit_mntopts(tmp, &fs_param.s_default_mount_opts);
1998 if (tmp)
1999 free(tmp);
2000
9b27e9cc
TT
2001 for (cpp = fs_types; *cpp; cpp++) {
2002 tmp = NULL;
2003 profile_get_string(profile, "fs_types", *cpp,
2004 "features", "", &tmp);
2005 if (tmp && *tmp)
2006 edit_feature(tmp, &fs_param.s_feature_compat);
2007 if (tmp)
2008 free(tmp);
2009 }
2010 tmp = get_string_from_profile(fs_types, "default_features",
2011 "");
2012 }
48b35e23
TT
2013 /* Mask off features which aren't supported by the Hurd */
2014 if (for_hurd(creator_os)) {
7889640d
DW
2015 ext2fs_clear_feature_filetype(&fs_param);
2016 ext2fs_clear_feature_huge_file(&fs_param);
2017 ext2fs_clear_feature_metadata_csum(&fs_param);
cfc8fae3 2018 ext2fs_clear_feature_ea_inode(&fs_param);
48b35e23 2019 }
9b27e9cc
TT
2020 edit_feature(fs_features ? fs_features : tmp,
2021 &fs_param.s_feature_compat);
2022 if (tmp)
2023 free(tmp);
a039df9c 2024 (void) ext2fs_free_mem(&fs_features);
48b35e23
TT
2025 /*
2026 * If the user specified features incompatible with the Hurd, complain
2027 */
2028 if (for_hurd(creator_os)) {
7889640d 2029 if (ext2fs_has_feature_filetype(&fs_param)) {
bbccc6f3
AD
2030 fprintf(stderr, "%s", _("The HURD does not support the "
2031 "filetype feature.\n"));
48b35e23
TT
2032 exit(1);
2033 }
7889640d 2034 if (ext2fs_has_feature_huge_file(&fs_param)) {
bbccc6f3
AD
2035 fprintf(stderr, "%s", _("The HURD does not support the "
2036 "huge_file feature.\n"));
48b35e23
TT
2037 exit(1);
2038 }
7889640d 2039 if (ext2fs_has_feature_metadata_csum(&fs_param)) {
bbccc6f3
AD
2040 fprintf(stderr, "%s", _("The HURD does not support the "
2041 "metadata_csum feature.\n"));
48b35e23
TT
2042 exit(1);
2043 }
cfc8fae3
TE
2044 if (ext2fs_has_feature_ea_inode(&fs_param)) {
2045 fprintf(stderr, "%s", _("The HURD does not support the "
2046 "ea_inode feature.\n"));
2047 exit(1);
2048 }
48b35e23 2049 }
9b27e9cc 2050
d20403df
DW
2051 /* Get the hardware sector sizes, if available */
2052 retval = ext2fs_get_device_sectsize(device_name, &lsector_size);
2053 if (retval) {
45ff69ff 2054 com_err(program_name, retval, "%s",
d20403df
DW
2055 _("while trying to determine hardware sector size"));
2056 exit(1);
2057 }
2058 retval = ext2fs_get_device_phys_sectsize(device_name, &psector_size);
2059 if (retval) {
45ff69ff 2060 com_err(program_name, retval, "%s",
d20403df
DW
2061 _("while trying to determine physical sector size"));
2062 exit(1);
2063 }
2064
2065 tmp = getenv("MKE2FS_DEVICE_SECTSIZE");
2066 if (tmp != NULL)
2067 lsector_size = atoi(tmp);
2068 tmp = getenv("MKE2FS_DEVICE_PHYS_SECTSIZE");
2069 if (tmp != NULL)
2070 psector_size = atoi(tmp);
2071
2072 /* Older kernels may not have physical/logical distinction */
2073 if (!psector_size)
2074 psector_size = lsector_size;
2075
2076 if (blocksize <= 0) {
2077 use_bsize = get_int_from_profile(fs_types, "blocksize", 4096);
2078
2079 if (use_bsize == -1) {
2080 use_bsize = sys_page_size;
d27a559c 2081 if (is_before_linux_ver(2, 6, 0) && use_bsize > 4096)
d20403df
DW
2082 use_bsize = 4096;
2083 }
2084 if (lsector_size && use_bsize < lsector_size)
2085 use_bsize = lsector_size;
2086 if ((blocksize < 0) && (use_bsize < (-blocksize)))
2087 use_bsize = -blocksize;
2088 blocksize = use_bsize;
2089 fs_blocks_count /= (blocksize / 1024);
2090 } else {
2091 if (blocksize < lsector_size) { /* Impossible */
45ff69ff 2092 com_err(program_name, EINVAL, "%s",
d20403df
DW
2093 _("while setting blocksize; too small "
2094 "for device\n"));
2095 exit(1);
2096 } else if ((blocksize < psector_size) &&
2097 (psector_size <= sys_page_size)) { /* Suboptimal */
2098 fprintf(stderr, _("Warning: specified blocksize %d is "
2099 "less than device physical sectorsize %d\n"),
2100 blocksize, psector_size);
2101 }
2102 }
2103
2104 fs_param.s_log_block_size =
2105 int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
2106
493024ea
TT
2107 /*
2108 * We now need to do a sanity check of fs_blocks_count for
2109 * 32-bit vs 64-bit block number support.
2110 */
9aef4b69 2111 if ((fs_blocks_count > MAX_32_NUM) &&
7889640d
DW
2112 ext2fs_has_feature_64bit(&fs_param))
2113 ext2fs_clear_feature_resize_inode(&fs_param);
493024ea 2114 if ((fs_blocks_count > MAX_32_NUM) &&
7889640d 2115 !ext2fs_has_feature_64bit(&fs_param) &&
493024ea 2116 get_bool_from_profile(fs_types, "auto_64-bit_support", 0)) {
7889640d
DW
2117 ext2fs_set_feature_64bit(&fs_param);
2118 ext2fs_clear_feature_resize_inode(&fs_param);
493024ea
TT
2119 }
2120 if ((fs_blocks_count > MAX_32_NUM) &&
7889640d 2121 !ext2fs_has_feature_64bit(&fs_param)) {
493024ea
TT
2122 fprintf(stderr, _("%s: Size of device (0x%llx blocks) %s "
2123 "too big to be expressed\n\t"
2124 "in 32 bits using a blocksize of %d.\n"),
2125 program_name, fs_blocks_count, device_name,
2126 EXT2_BLOCK_SIZE(&fs_param));
2127 exit(1);
2128 }
101ef2e9
JK
2129 /*
2130 * Guard against group descriptor count overflowing... Mostly to avoid
2131 * strange results for absurdly large devices.
2132 */
2133 if (fs_blocks_count > ((1ULL << (fs_param.s_log_block_size + 3 + 32)) - 1)) {
2134 fprintf(stderr, _("%s: Size of device (0x%llx blocks) %s "
2135 "too big to create\n\t"
2136 "a filesystem using a blocksize of %d.\n"),
2137 program_name, fs_blocks_count, device_name,
2138 EXT2_BLOCK_SIZE(&fs_param));
2139 exit(1);
2140 }
493024ea
TT
2141
2142 ext2fs_blocks_count_set(&fs_param, fs_blocks_count);
2143
7889640d 2144 if (ext2fs_has_feature_journal_dev(&fs_param)) {
a54733d2
TT
2145 int i;
2146
2147 for (i=0; fs_types[i]; i++) {
2148 free(fs_types[i]);
2149 fs_types[i] = 0;
2150 }
b4d5105b
TT
2151 fs_types[0] = strdup("journal");
2152 fs_types[1] = 0;
2153 }
2154
2155 if (verbose) {
2156 fputs(_("fs_types for mke2fs.conf resolution: "), stdout);
2157 print_str_list(fs_types);
2158 }
2159
efc6f628 2160 if (r_opt == EXT2_GOOD_OLD_REV &&
b290d2dc 2161 (fs_param.s_feature_compat || fs_param.s_feature_incompat ||
92fb8545 2162 fs_param.s_feature_ro_compat)) {
45ff69ff
AD
2163 fprintf(stderr, "%s", _("Filesystem features not supported "
2164 "with revision 0 filesystems\n"));
9dc6ad1e
TT
2165 exit(1);
2166 }
2167
b290d2dc
TT
2168 if (s_opt > 0) {
2169 if (r_opt == EXT2_GOOD_OLD_REV) {
45ff69ff
AD
2170 fprintf(stderr, "%s",
2171 _("Sparse superblocks not supported "
b290d2dc
TT
2172 "with revision 0 filesystems\n"));
2173 exit(1);
2174 }
7889640d 2175 ext2fs_set_feature_sparse_super(&fs_param);
b290d2dc 2176 } else if (s_opt == 0)
7889640d 2177 ext2fs_clear_feature_sparse_super(&fs_param);
9dc6ad1e 2178
b290d2dc
TT
2179 if (journal_size != 0) {
2180 if (r_opt == EXT2_GOOD_OLD_REV) {
45ff69ff
AD
2181 fprintf(stderr, "%s", _("Journals not supported with "
2182 "revision 0 filesystems\n"));
b290d2dc
TT
2183 exit(1);
2184 }
7889640d 2185 ext2fs_set_feature_journal(&fs_param);
b290d2dc 2186 }
9dc6ad1e 2187
d3859af3
AK
2188 /* Get reserved_ratio from profile if not specified on cmd line. */
2189 if (reserved_ratio < 0.0) {
2190 reserved_ratio = get_double_from_profile(
2191 fs_types, "reserved_ratio", 5.0);
2192 if (reserved_ratio > 50 || reserved_ratio < 0) {
2193 com_err(program_name, 0,
2194 _("invalid reserved blocks percent - %lf"),
2195 reserved_ratio);
2196 exit(1);
2197 }
2198 }
2199
7889640d 2200 if (ext2fs_has_feature_journal_dev(&fs_param)) {
9dc6ad1e
TT
2201 reserved_ratio = 0;
2202 fs_param.s_feature_incompat = EXT3_FEATURE_INCOMPAT_JOURNAL_DEV;
2203 fs_param.s_feature_compat = 0;
7a8f4973
DW
2204 fs_param.s_feature_ro_compat &=
2205 EXT4_FEATURE_RO_COMPAT_METADATA_CSUM;
9dc6ad1e 2206 }
d94cc2ea 2207
d11f92af 2208 /* Check the user's mkfs options for 64bit */
7889640d
DW
2209 if (ext2fs_has_feature_64bit(&fs_param) &&
2210 !ext2fs_has_feature_extents(&fs_param)) {
45ff69ff
AD
2211 printf("%s", _("Extents MUST be enabled for a 64-bit "
2212 "filesystem. Pass -O extents to rectify.\n"));
d11f92af
DW
2213 exit(1);
2214 }
2215
c046ac7f
TT
2216 /* Set first meta blockgroup via an environment variable */
2217 /* (this is mostly for debugging purposes) */
7889640d
DW
2218 if (ext2fs_has_feature_meta_bg(&fs_param) &&
2219 (tmp = getenv("MKE2FS_FIRST_META_BG")))
9b9a780f 2220 fs_param.s_first_meta_bg = atoi(tmp);
7889640d 2221 if (ext2fs_has_feature_bigalloc(&fs_param)) {
2d34a25f
TT
2222 if (!cluster_size)
2223 cluster_size = get_int_from_profile(fs_types,
2224 "cluster_size",
b12a0bc3 2225 blocksize*16);
2d34a25f
TT
2226 fs_param.s_log_cluster_size =
2227 int_log2(cluster_size >> EXT2_MIN_CLUSTER_LOG_SIZE);
4b20ea26
TT
2228 if (fs_param.s_log_cluster_size &&
2229 fs_param.s_log_cluster_size < fs_param.s_log_block_size) {
45ff69ff 2230 com_err(program_name, 0, "%s",
4b20ea26
TT
2231 _("The cluster size may not be "
2232 "smaller than the block size.\n"));
2233 exit(1);
2234 }
9cf69bb8 2235 } else if (cluster_size) {
45ff69ff 2236 com_err(program_name, 0, "%s",
9cf69bb8
ZL
2237 _("specifying a cluster size requires the "
2238 "bigalloc feature"));
2239 exit(1);
c6ed60cd
TT
2240 } else
2241 fs_param.s_log_cluster_size = fs_param.s_log_block_size;
2242
9dc6ad1e 2243 if (inode_ratio == 0) {
3d43836f
TT
2244 inode_ratio = get_int_from_profile(fs_types, "inode_ratio",
2245 8192);
9dc6ad1e
TT
2246 if (inode_ratio < blocksize)
2247 inode_ratio = blocksize;
c6ed60cd
TT
2248 if (inode_ratio < EXT2_CLUSTER_SIZE(&fs_param))
2249 inode_ratio = EXT2_CLUSTER_SIZE(&fs_param);
9dc6ad1e
TT
2250 }
2251
9ed8e5fe 2252#ifdef HAVE_BLKID_PROBE_GET_TOPOLOGY
4e222d9b
TT
2253 retval = get_device_geometry(device_name, &fs_param,
2254 (unsigned int) psector_size);
9ed8e5fe
ES
2255 if (retval < 0) {
2256 fprintf(stderr,
13b0b123 2257 _("warning: Unable to get device geometry for %s\n"),
9ed8e5fe
ES
2258 device_name);
2259 } else if (retval) {
2260 printf(_("%s alignment is offset by %lu bytes.\n"),
2261 device_name, retval);
2262 printf(_("This may result in very poor performance, "
2263 "(re)-partitioning suggested.\n"));
9ed8e5fe
ES
2264 }
2265#endif
2266
65c6c3e0
TT
2267 num_backups = get_int_from_profile(fs_types, "num_backup_sb", 2);
2268
9b9a780f 2269 blocksize = EXT2_BLOCK_SIZE(&fs_param);
a4396e9d 2270
49cdefd3
TT
2271 /*
2272 * Initialize s_desc_size so that the parse_extended_opts()
2273 * can correctly handle "-E resize=NNN" if the 64-bit option
2274 * is set.
2275 */
7889640d 2276 if (ext2fs_has_feature_64bit(&fs_param))
49cdefd3
TT
2277 fs_param.s_desc_size = EXT2_MIN_DESC_SIZE_64BIT;
2278
45792c12
YZ
2279 /* This check should happen beyond the last assignment to blocksize */
2280 if (blocksize > sys_page_size) {
2281 if (!force) {
2282 com_err(program_name, 0,
2283 _("%d-byte blocks too big for system (max %d)"),
2284 blocksize, sys_page_size);
f83f4132 2285 proceed_question(proceed_delay);
45792c12
YZ
2286 }
2287 fprintf(stderr, _("Warning: %d-byte blocks too big for system "
2288 "(max %d), forced to continue\n"),
2289 blocksize, sys_page_size);
2290 }
2291
210baa5d
DW
2292 /* Metadata checksumming wasn't totally stable before 3.18. */
2293 if (is_before_linux_ver(3, 18, 0) &&
7889640d 2294 ext2fs_has_feature_metadata_csum(&fs_param))
210baa5d
DW
2295 fprintf(stderr, _("Suggestion: Use Linux kernel >= 3.18 for "
2296 "improved stability of the metadata and journal "
2297 "checksum features.\n"));
2298
7584b8db
LC
2299 /*
2300 * On newer kernels we do have lazy_itable_init support. So pick the
2301 * right default in case ext4 module is not loaded.
2302 */
2303 if (is_before_linux_ver(2, 6, 37))
2304 lazy_itable_init = 0;
2305 else
2306 lazy_itable_init = 1;
2307
210fd2c7
TT
2308 if (access("/sys/fs/ext4/features/lazy_itable_init", R_OK) == 0)
2309 lazy_itable_init = 1;
2310
efc6f628 2311 lazy_itable_init = get_bool_from_profile(fs_types,
210fd2c7
TT
2312 "lazy_itable_init",
2313 lazy_itable_init);
7fe5ff3c 2314 discard = get_bool_from_profile(fs_types, "discard" , discard);
6c54689f
AD
2315 journal_flags |= get_bool_from_profile(fs_types,
2316 "lazy_journal_init", 0) ?
2317 EXT2_MKJOURNAL_LAZYINIT : 0;
304e11c2 2318 journal_flags |= EXT2_MKJOURNAL_NO_MNT_CHECK;
efc6f628 2319
b818205f
TT
2320 if (!journal_location_string)
2321 journal_location_string = get_string_from_profile(fs_types,
2322 "journal_location", "");
2323 if ((journal_location == ~0ULL) && journal_location_string &&
2324 *journal_location_string)
2325 journal_location = parse_num_blocks2(journal_location_string,
2326 fs_param.s_log_block_size);
2327 free(journal_location_string);
2328
3c6e91c5
TT
2329 packed_meta_blocks = get_bool_from_profile(fs_types,
2330 "packed_meta_blocks", 0);
2331 if (packed_meta_blocks)
2332 journal_location = 0;
2333
2d36358d
TT
2334 /* Get options from profile */
2335 for (cpp = fs_types; *cpp; cpp++) {
2336 tmp = NULL;
2337 profile_get_string(profile, "fs_types", *cpp, "options", "", &tmp);
2338 if (tmp && *tmp)
2339 parse_extended_opts(&fs_param, tmp);
45e338f5 2340 free(tmp);
2d36358d
TT
2341 }
2342
c6a44136 2343 if (extended_opts)
9b9a780f 2344 parse_extended_opts(&fs_param, extended_opts);
d323f8fb 2345
87d9b2fb
TT
2346 if (explicit_fssize == 0 && offset > 0) {
2347 fs_blocks_count -= offset / EXT2_BLOCK_SIZE(&fs_param);
2348 ext2fs_blocks_count_set(&fs_param, fs_blocks_count);
2349 fprintf(stderr,
2350 _("\nWarning: offset specified without an "
2351 "explicit file system size.\n"
a195e862 2352 "Creating a file system with %llu blocks "
87d9b2fb 2353 "but this might\n"
a195e862
TT
2354 "not be what you want.\n\n"),
2355 (unsigned long long) fs_blocks_count);
87d9b2fb
TT
2356 }
2357
66aae965
TT
2358 if (quotatype_bits & QUOTA_PRJ_BIT)
2359 ext2fs_set_feature_project(&fs_param);
2360
2361 if (ext2fs_has_feature_project(&fs_param)) {
2362 quotatype_bits |= QUOTA_PRJ_BIT;
2363 if (inode_size == EXT2_GOOD_OLD_INODE_SIZE) {
2364 com_err(program_name, 0,
2365 _("%d byte inodes are too small for "
2366 "project quota"),
2367 inode_size);
2368 exit(1);
2369 }
2370 if (inode_size == 0) {
2371 inode_size = get_int_from_profile(fs_types,
2372 "inode_size", 0);
2373 if (inode_size <= EXT2_GOOD_OLD_INODE_SIZE*2)
2374 inode_size = EXT2_GOOD_OLD_INODE_SIZE*2;
2375 }
2376 }
2377
ef5b606c 2378 /* Don't allow user to set both metadata_csum and uninit_bg bits. */
7889640d
DW
2379 if (ext2fs_has_feature_metadata_csum(&fs_param) &&
2380 ext2fs_has_feature_gdt_csum(&fs_param))
2381 ext2fs_clear_feature_gdt_csum(&fs_param);
ef5b606c 2382
f45011df 2383 /* Can't support bigalloc feature without extents feature */
7889640d
DW
2384 if (ext2fs_has_feature_bigalloc(&fs_param) &&
2385 !ext2fs_has_feature_extents(&fs_param)) {
45ff69ff 2386 com_err(program_name, 0, "%s",
f45011df
ZL
2387 _("Can't support bigalloc feature without "
2388 "extents feature"));
2389 exit(1);
2390 }
2391
7889640d
DW
2392 if (ext2fs_has_feature_meta_bg(&fs_param) &&
2393 ext2fs_has_feature_resize_inode(&fs_param)) {
45ff69ff
AD
2394 fprintf(stderr, "%s", _("The resize_inode and meta_bg "
2395 "features are not compatible.\n"
2396 "They can not be both enabled "
2397 "simultaneously.\n"));
cecfb4c0
TT
2398 exit(1);
2399 }
2400
7889640d 2401 if (!quiet && ext2fs_has_feature_bigalloc(&fs_param))
45ff69ff
AD
2402 fprintf(stderr, "%s", _("\nWarning: the bigalloc feature is "
2403 "still under development\n"
a713a7fe
TT
2404 "See https://ext4.wiki.kernel.org/"
2405 "index.php/Bigalloc for more information\n\n"));
2406
b451c8dd
ZL
2407 /*
2408 * Since sparse_super is the default, we would only have a problem
d323f8fb
TT
2409 * here if it was explicitly disabled.
2410 */
7889640d
DW
2411 if (ext2fs_has_feature_resize_inode(&fs_param) &&
2412 !ext2fs_has_feature_sparse_super(&fs_param)) {
45ff69ff 2413 com_err(program_name, 0, "%s",
d323f8fb
TT
2414 _("reserved online resize blocks not supported "
2415 "on non-sparse filesystem"));
2416 exit(1);
2417 }
2418
9b9a780f
TT
2419 if (fs_param.s_blocks_per_group) {
2420 if (fs_param.s_blocks_per_group < 256 ||
2421 fs_param.s_blocks_per_group > 8 * (unsigned) blocksize) {
45ff69ff 2422 com_err(program_name, 0, "%s",
d9c56d3c 2423 _("blocks per group count out of range"));
521e3685
TT
2424 exit(1);
2425 }
2426 }
2427
2a3b1c6e
TT
2428 /*
2429 * If the bigalloc feature is enabled, then the -g option will
2430 * specify the number of clusters per group.
2431 */
7889640d 2432 if (ext2fs_has_feature_bigalloc(&fs_param)) {
2a3b1c6e
TT
2433 fs_param.s_clusters_per_group = fs_param.s_blocks_per_group;
2434 fs_param.s_blocks_per_group = 0;
2435 }
2436
3d43836f
TT
2437 if (inode_size == 0)
2438 inode_size = get_int_from_profile(fs_types, "inode_size", 0);
7889640d 2439 if (!flex_bg_size && ext2fs_has_feature_flex_bg(&fs_param))
d0de4c95
AF
2440 flex_bg_size = get_uint_from_profile(fs_types,
2441 "flex_bg_size", 16);
9ba40002 2442 if (flex_bg_size) {
7889640d 2443 if (!ext2fs_has_feature_flex_bg(&fs_param)) {
45ff69ff 2444 com_err(program_name, 0, "%s",
9ba40002
TT
2445 _("Flex_bg feature not enabled, so "
2446 "flex_bg size may not be specified"));
2447 exit(1);
2448 }
2449 fs_param.s_log_groups_per_flex = int_log2(flex_bg_size);
2450 }
067911ae
AD
2451
2452 if (inode_size && fs_param.s_rev_level >= EXT2_DYNAMIC_REV) {
932a489c 2453 if (inode_size < EXT2_GOOD_OLD_INODE_SIZE ||
9b9a780f 2454 inode_size > EXT2_BLOCK_SIZE(&fs_param) ||
932a489c
AD
2455 inode_size & (inode_size - 1)) {
2456 com_err(program_name, 0,
bb145b01 2457 _("invalid inode size %d (min %d/max %d)"),
932a489c 2458 inode_size, EXT2_GOOD_OLD_INODE_SIZE,
c5290fae 2459 blocksize);
932a489c
AD
2460 exit(1);
2461 }
9b9a780f 2462 fs_param.s_inode_size = inode_size;
932a489c
AD
2463 }
2464
c6bab651
DW
2465 /*
2466 * If inode size is 128 and inline data is enabled, we need
2467 * to notify users that inline data will never be useful.
2468 */
7889640d 2469 if (ext2fs_has_feature_inline_data(&fs_param) &&
c6bab651
DW
2470 fs_param.s_inode_size == EXT2_GOOD_OLD_INODE_SIZE) {
2471 com_err(program_name, 0,
5ae83d65
EW
2472 _("%d byte inodes are too small for inline data; "
2473 "specify larger size"),
c6bab651
DW
2474 fs_param.s_inode_size);
2475 exit(1);
2476 }
2477
f3358643
ES
2478 /* Make sure number of inodes specified will fit in 32 bits */
2479 if (num_inodes == 0) {
de8f3a76 2480 unsigned long long n;
4efbac6f 2481 n = ext2fs_blocks_count(&fs_param) * blocksize / inode_ratio;
493024ea 2482 if (n > MAX_32_NUM) {
7889640d 2483 if (ext2fs_has_feature_64bit(&fs_param))
493024ea 2484 num_inodes = MAX_32_NUM;
02d6f47e
JS
2485 else {
2486 com_err(program_name, 0,
84888e55 2487 _("too many inodes (%llu), raise "
02d6f47e
JS
2488 "inode ratio?"), n);
2489 exit(1);
2490 }
f3358643 2491 }
493024ea 2492 } else if (num_inodes > MAX_32_NUM) {
f3358643
ES
2493 com_err(program_name, 0,
2494 _("too many inodes (%llu), specify < 2^32 inodes"),
de8f3a76 2495 num_inodes);
f3358643
ES
2496 exit(1);
2497 }
3839e657
TT
2498 /*
2499 * Calculate number of inodes based on the inode ratio
2500 */
efc6f628 2501 fs_param.s_inodes_count = num_inodes ? num_inodes :
4efbac6f 2502 (ext2fs_blocks_count(&fs_param) * blocksize) / inode_ratio;
3839e657 2503
577c773a 2504 if ((((unsigned long long)fs_param.s_inodes_count) *
dcf7b091 2505 (inode_size ? inode_size : EXT2_GOOD_OLD_INODE_SIZE)) >=
4efbac6f 2506 ((ext2fs_blocks_count(&fs_param)) *
dcf7b091
AD
2507 EXT2_BLOCK_SIZE(&fs_param))) {
2508 com_err(program_name, 0, _("inode_size (%u) * inodes_count "
2509 "(%u) too big for a\n\t"
4efbac6f 2510 "filesystem with %llu blocks, "
dcf7b091
AD
2511 "specify higher inode_ratio (-i)\n\t"
2512 "or lower inode count (-N).\n"),
2513 inode_size ? inode_size : EXT2_GOOD_OLD_INODE_SIZE,
efc6f628 2514 fs_param.s_inodes_count,
4efbac6f 2515 (unsigned long long) ext2fs_blocks_count(&fs_param));
dcf7b091
AD
2516 exit(1);
2517 }
2518
3839e657
TT
2519 /*
2520 * Calculate number of blocks to reserve
2521 */
4efbac6f
VAH
2522 ext2fs_r_blocks_count_set(&fs_param, reserved_ratio *
2523 ext2fs_blocks_count(&fs_param) / 100.0);
4c2b28ab 2524
7889640d 2525 if (ext2fs_has_feature_sparse_super2(&fs_param)) {
65c6c3e0
TT
2526 if (num_backups >= 1)
2527 fs_param.s_backup_bgs[0] = 1;
2528 if (num_backups >= 2)
2529 fs_param.s_backup_bgs[1] = ~0;
2530 }
2531
4c2b28ab
TT
2532 free(fs_type);
2533 free(usage_types);
3839e657 2534}
d323f8fb 2535
b626b39a
AK
2536static int should_do_undo(const char *name)
2537{
2538 errcode_t retval;
2539 io_channel channel;
2540 __u16 s_magic;
2541 struct ext2_super_block super;
2542 io_manager manager = unix_io_manager;
2543 int csum_flag, force_undo;
2544
7889640d
DW
2545 csum_flag = ext2fs_has_feature_metadata_csum(&fs_param) ||
2546 ext2fs_has_feature_gdt_csum(&fs_param);
b626b39a
AK
2547 force_undo = get_int_from_profile(fs_types, "force_undo", 0);
2548 if (!force_undo && (!csum_flag || !lazy_itable_init))
2549 return 0;
2550
2551 retval = manager->open(name, IO_FLAG_EXCLUSIVE, &channel);
2552 if (retval) {
2553 /*
2554 * We don't handle error cases instead we
2555 * declare that the file system doesn't exist
2556 * and let the rest of mke2fs take care of
2557 * error
2558 */
2559 retval = 0;
2560 goto open_err_out;
2561 }
2562
2563 io_channel_set_blksize(channel, SUPERBLOCK_OFFSET);
24a117ab 2564 retval = io_channel_read_blk64(channel, 1, -SUPERBLOCK_SIZE, &super);
b626b39a
AK
2565 if (retval) {
2566 retval = 0;
2567 goto err_out;
2568 }
2569
2570#if defined(WORDS_BIGENDIAN)
2571 s_magic = ext2fs_swab16(super.s_magic);
2572#else
2573 s_magic = super.s_magic;
2574#endif
2575
2576 if (s_magic == EXT2_SUPER_MAGIC)
2577 retval = 1;
2578
2579err_out:
2580 io_channel_close(channel);
2581
2582open_err_out:
2583
2584 return retval;
2585}
2586
2587static int mke2fs_setup_tdb(const char *name, io_manager *io_ptr)
2588{
8a1cf3c2 2589 errcode_t retval = ENOMEM;
30295f16 2590 char *tdb_dir = NULL, *tdb_file = NULL;
577c773a 2591 char *dev_name, *tmp_name;
30295f16 2592 int free_tdb_dir = 0;
b626b39a 2593
2d291b3c
DW
2594 /* (re)open a specific undo file */
2595 if (undo_file && undo_file[0] != 0) {
b0851392
DW
2596 retval = set_undo_io_backing_manager(*io_ptr);
2597 if (retval)
2598 goto err;
2d291b3c
DW
2599 *io_ptr = undo_io_manager;
2600 retval = set_undo_io_backup_file(undo_file);
2601 if (retval)
2602 goto err;
2603 printf(_("Overwriting existing filesystem; this can be undone "
2604 "using the command:\n"
2605 " e2undo %s %s\n\n"), undo_file, name);
b0851392 2606 return retval;
2d291b3c
DW
2607 }
2608
b626b39a
AK
2609 /*
2610 * Configuration via a conf file would be
2611 * nice
2612 */
2613 tdb_dir = getenv("E2FSPROGS_UNDO_DIR");
30295f16 2614 if (!tdb_dir) {
b626b39a
AK
2615 profile_get_string(profile, "defaults",
2616 "undo_dir", 0, "/var/lib/e2fsprogs",
2617 &tdb_dir);
30295f16
ES
2618 free_tdb_dir = 1;
2619 }
b626b39a
AK
2620
2621 if (!strcmp(tdb_dir, "none") || (tdb_dir[0] == 0) ||
80a1806d
DW
2622 access(tdb_dir, W_OK)) {
2623 if (free_tdb_dir)
2624 free(tdb_dir);
b626b39a 2625 return 0;
80a1806d 2626 }
b626b39a
AK
2627
2628 tmp_name = strdup(name);
8a1cf3c2
TT
2629 if (!tmp_name)
2630 goto errout;
577c773a
TT
2631 dev_name = basename(tmp_name);
2632 tdb_file = malloc(strlen(tdb_dir) + 8 + strlen(dev_name) + 7 + 1);
8a1cf3c2
TT
2633 if (!tdb_file) {
2634 free(tmp_name);
2635 goto errout;
2636 }
577c773a 2637 sprintf(tdb_file, "%s/mke2fs-%s.e2undo", tdb_dir, dev_name);
8a1cf3c2 2638 free(tmp_name);
b626b39a 2639
250bf9a7
TT
2640 if ((unlink(tdb_file) < 0) && (errno != ENOENT)) {
2641 retval = errno;
b0851392
DW
2642 com_err(program_name, retval,
2643 _("while trying to delete %s"), tdb_file);
250bf9a7 2644 goto errout;
b626b39a
AK
2645 }
2646
b0851392
DW
2647 retval = set_undo_io_backing_manager(*io_ptr);
2648 if (retval)
2649 goto errout;
b626b39a 2650 *io_ptr = undo_io_manager;
8a1cf3c2
TT
2651 retval = set_undo_io_backup_file(tdb_file);
2652 if (retval)
2653 goto errout;
b626b39a
AK
2654 printf(_("Overwriting existing filesystem; this can be undone "
2655 "using the command:\n"
2656 " e2undo %s %s\n\n"), tdb_file, name);
79e62409 2657
30295f16
ES
2658 if (free_tdb_dir)
2659 free(tdb_dir);
f203bbdb 2660 free(tdb_file);
8a1cf3c2
TT
2661 return 0;
2662
2663errout:
30295f16
ES
2664 if (free_tdb_dir)
2665 free(tdb_dir);
8a1cf3c2 2666 free(tdb_file);
2d291b3c 2667err:
45ff69ff 2668 com_err(program_name, retval, "%s",
8a1cf3c2 2669 _("while trying to setup undo file\n"));
b626b39a
AK
2670 return retval;
2671}
2672
7d9e3165
LC
2673static int mke2fs_discard_device(ext2_filsys fs)
2674{
2675 struct ext2fs_numeric_progress_struct progress;
2676 blk64_t blocks = ext2fs_blocks_count(fs->super);
2677 blk64_t count = DISCARD_STEP_MB;
d2bfdc7f 2678 blk64_t cur;
7d9e3165
LC
2679 int retval = 0;
2680
d2bfdc7f
LC
2681 /*
2682 * Let's try if discard really works on the device, so
2683 * we do not print numeric progress resulting in failure
2684 * afterwards.
2685 */
2686 retval = io_channel_discard(fs->io, 0, fs->blocksize);
aa07cb79
TT
2687 if (retval)
2688 return retval;
d2bfdc7f 2689 cur = fs->blocksize;
aa07cb79 2690
7d9e3165
LC
2691 count *= (1024 * 1024);
2692 count /= fs->blocksize;
2693
2694 ext2fs_numeric_progress_init(fs, &progress,
2695 _("Discarding device blocks: "),
2696 blocks);
2697 while (cur < blocks) {
c498cb11 2698 ext2fs_numeric_progress_update(fs, &progress, cur);
7d9e3165
LC
2699
2700 if (cur + count > blocks)
2701 count = blocks - cur;
2702
aa07cb79 2703 retval = io_channel_discard(fs->io, cur, count);
7d9e3165
LC
2704 if (retval)
2705 break;
2706 cur += count;
2707 }
2708
2709 if (retval) {
2710 ext2fs_numeric_progress_close(fs, &progress,
2711 _("failed - "));
2712 if (!quiet)
2713 printf("%s\n",error_message(retval));
2714 } else
2715 ext2fs_numeric_progress_close(fs, &progress,
2716 _("done \n"));
2717
2718 return retval;
2719}
2720
96367ad3 2721static void fix_cluster_bg_counts(ext2_filsys fs)
c6ed60cd 2722{
6e49e6a3
TT
2723 blk64_t block, num_blocks, last_block, next;
2724 blk64_t tot_free = 0;
2725 errcode_t retval;
2726 dgrp_t group = 0;
2727 int grp_free = 0;
2728
2729 num_blocks = ext2fs_blocks_count(fs->super);
2730 last_block = ext2fs_group_last_block2(fs, group);
2731 block = fs->super->s_first_data_block;
2732 while (block < num_blocks) {
2733 retval = ext2fs_find_first_zero_block_bitmap2(fs->block_map,
2734 block, last_block, &next);
2735 if (retval == 0)
2736 block = next;
2737 else {
2738 block = last_block + 1;
2739 goto next_bg;
c6ed60cd 2740 }
6e49e6a3
TT
2741
2742 retval = ext2fs_find_first_set_block_bitmap2(fs->block_map,
2743 block, last_block, &next);
2744 if (retval)
2745 next = last_block + 1;
2746 grp_free += EXT2FS_NUM_B2C(fs, next - block);
2747 tot_free += next - block;
2748 block = next;
2749
2750 if (block > last_block) {
2751 next_bg:
c6ed60cd
TT
2752 ext2fs_bg_free_blocks_count_set(fs, group, grp_free);
2753 ext2fs_group_desc_csum_set(fs, group);
c6ed60cd
TT
2754 grp_free = 0;
2755 group++;
6e49e6a3 2756 last_block = ext2fs_group_last_block2(fs, group);
c6ed60cd
TT
2757 }
2758 }
6e49e6a3 2759 ext2fs_free_blocks_count_set(fs->super, tot_free);
c6ed60cd
TT
2760}
2761
1f5d7a89
AK
2762static int create_quota_inodes(ext2_filsys fs)
2763{
2764 quota_ctx_t qctx;
a701823a 2765 errcode_t retval;
1f5d7a89 2766
5c2a665a 2767 retval = quota_init_context(&qctx, fs, quotatype_bits);
a701823a
TT
2768 if (retval) {
2769 com_err(program_name, retval,
2770 _("while initializing quota context"));
2771 exit(1);
2772 }
a86d55da 2773 quota_compute_usage(qctx);
a701823a
TT
2774 retval = quota_write_inode(qctx, quotatype_bits);
2775 if (retval) {
2776 com_err(program_name, retval,
2777 _("while writing quota inodes"));
2778 exit(1);
2779 }
a86d55da 2780 quota_release_context(&qctx);
1f5d7a89 2781
a86d55da 2782 return 0;
1f5d7a89
AK
2783}
2784
cd32129d
DW
2785static errcode_t set_error_behavior(ext2_filsys fs)
2786{
2787 char *arg = NULL;
2788 short errors = fs->super->s_errors;
2789
2790 arg = get_string_from_profile(fs_types, "errors", NULL);
2791 if (arg == NULL)
2792 goto try_user;
2793
2794 if (strcmp(arg, "continue") == 0)
2795 errors = EXT2_ERRORS_CONTINUE;
2796 else if (strcmp(arg, "remount-ro") == 0)
2797 errors = EXT2_ERRORS_RO;
2798 else if (strcmp(arg, "panic") == 0)
2799 errors = EXT2_ERRORS_PANIC;
2800 else {
2801 com_err(program_name, 0,
2802 _("bad error behavior in profile - %s"),
2803 arg);
2804 free(arg);
2805 return EXT2_ET_INVALID_ARGUMENT;
2806 }
2807 free(arg);
2808
2809try_user:
2810 if (errors_behavior)
2811 errors = errors_behavior;
2812
2813 fs->super->s_errors = errors;
2814 return 0;
2815}
2816
3839e657
TT
2817int main (int argc, char *argv[])
2818{
2819 errcode_t retval = 0;
2820 ext2_filsys fs;
2821 badblocks_list bb_list = 0;
d8f401b1 2822 unsigned int journal_blocks = 0;
14b283ae
TT
2823 unsigned int i, checkinterval;
2824 int max_mnt_count;
d5f57d95 2825 int val, hash_alg;
463e7327
VAH
2826 int flags;
2827 int old_bitmaps;
a7ccdff8 2828 io_manager io_ptr;
88ee023b 2829 char opt_string[40];
d5f57d95 2830 char *hash_alg_str;
6fcd6f84 2831 int itable_zeroed = 0;
d9c56d3c
TT
2832
2833#ifdef ENABLE_NLS
2834 setlocale(LC_MESSAGES, "");
14308a53 2835 setlocale(LC_CTYPE, "");
d9c56d3c
TT
2836 bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
2837 textdomain(NLS_CAT_NAME);
9d4507c5 2838 set_com_err_gettext(gettext);
d9c56d3c 2839#endif
3839e657
TT
2840 PRS(argc, argv);
2841
a7ccdff8 2842#ifdef CONFIG_TESTIO_DEBUG
f38cf3cb
TT
2843 if (getenv("TEST_IO_FLAGS") || getenv("TEST_IO_BLOCK")) {
2844 io_ptr = test_io_manager;
2845 test_io_backing_manager = unix_io_manager;
2846 } else
a7ccdff8 2847#endif
f38cf3cb 2848 io_ptr = unix_io_manager;
a7ccdff8 2849
2d291b3c 2850 if (undo_file != NULL || should_do_undo(device_name)) {
b626b39a
AK
2851 retval = mke2fs_setup_tdb(device_name, &io_ptr);
2852 if (retval)
2853 exit(1);
2854 }
2855
3839e657
TT
2856 /*
2857 * Initialize the superblock....
2858 */
463e7327 2859 flags = EXT2_FLAG_EXCLUSIVE;
37c8db7b
TT
2860 if (direct_io)
2861 flags |= EXT2_FLAG_DIRECT_IO;
463e7327
VAH
2862 profile_get_boolean(profile, "options", "old_bitmaps", 0, 0,
2863 &old_bitmaps);
2864 if (!old_bitmaps)
2865 flags |= EXT2_FLAG_64BITS;
95fd65bb
VAH
2866 /*
2867 * By default, we print how many inode tables or block groups
2868 * or whatever we've written so far. The quiet flag disables
2869 * this, along with a lot of other output.
2870 */
2871 if (!quiet)
2872 flags |= EXT2_FLAG_PRINT_PROGRESS;
105cdfe5
AS
2873 if (android_sparse_file) {
2874 android_sparse_params = malloc(PATH_MAX + 32);
2875 if (!android_sparse_params) {
2876 com_err(program_name, ENOMEM, "%s",
2877 _("in malloc for android_sparse_params"));
2878 exit(1);
2879 }
2d545e37 2880 snprintf(android_sparse_params, PATH_MAX + 32, "(%s):%u:%u",
105cdfe5
AS
2881 device_name, fs_param.s_blocks_count,
2882 1024 << fs_param.s_log_block_size);
2883 retval = ext2fs_initialize(android_sparse_params, flags,
2884 &fs_param, sparse_io_manager, &fs);
2885 } else
2886 retval = ext2fs_initialize(device_name, flags, &fs_param,
2887 io_ptr, &fs);
3839e657 2888 if (retval) {
45ff69ff
AD
2889 com_err(device_name, retval, "%s",
2890 _("while setting up superblock"));
3839e657
TT
2891 exit(1);
2892 }
dfe74c5c 2893 fs->progress_ops = &ext2fs_numeric_progress_ops;
95fd65bb 2894
cd32129d
DW
2895 /* Set the error behavior */
2896 retval = set_error_behavior(fs);
2897 if (retval)
2898 usage();
2899
2b588d73
DW
2900 /* Check the user's mkfs options for metadata checksumming */
2901 if (!quiet &&
7889640d
DW
2902 !ext2fs_has_feature_journal_dev(fs->super) &&
2903 ext2fs_has_feature_metadata_csum(fs->super)) {
2904 if (!ext2fs_has_feature_extents(fs->super))
bbccc6f3
AD
2905 printf("%s",
2906 _("Extents are not enabled. The file extent "
2b588d73
DW
2907 "tree can be checksummed, whereas block maps "
2908 "cannot. Not enabling extents reduces the "
2909 "coverage of metadata checksumming. "
2910 "Pass -O extents to rectify.\n"));
7889640d 2911 if (!ext2fs_has_feature_64bit(fs->super))
bbccc6f3
AD
2912 printf("%s",
2913 _("64-bit filesystem support is not enabled. "
2914 "The larger fields afforded by this feature "
2915 "enable full-strength checksumming. "
2916 "Pass -O 64bit to rectify.\n"));
2b588d73
DW
2917 }
2918
1b7623b8
DW
2919 if (ext2fs_has_feature_csum_seed(fs->super) &&
2920 !ext2fs_has_feature_metadata_csum(fs->super)) {
2921 printf("%s", _("The metadata_csum_seed feature "
8da7db5e 2922 "requires the metadata_csum feature.\n"));
1b7623b8
DW
2923 exit(1);
2924 }
2925
fd73a1d2
AS
2926 /* Calculate journal blocks */
2927 if (!journal_device && ((journal_size) ||
7889640d 2928 ext2fs_has_feature_journal(&fs_param)))
fd73a1d2
AS
2929 journal_blocks = figure_journal_size(journal_size, fs);
2930
cba3fd5c
MH
2931 sprintf(opt_string, "tdb_data_size=%d", fs->blocksize <= 4096 ?
2932 32768 : fs->blocksize * 8);
2933 io_channel_set_options(fs->io, opt_string);
2934 if (offset) {
2935 sprintf(opt_string, "offset=%llu", offset);
2936 io_channel_set_options(fs->io, opt_string);
2937 }
2938
5827d241 2939 /* Can't undo discard ... */
a11ccebd 2940 if (!noaction && discard && dev_size && (io_ptr != undo_io_manager)) {
7d9e3165 2941 retval = mke2fs_discard_device(fs);
d866599a 2942 if (!retval && io_channel_discard_zeroes_data(fs->io)) {
6fcd6f84 2943 if (verbose)
45ff69ff
AD
2944 printf("%s",
2945 _("Discard succeeded and will return "
2946 "0s - skipping inode table wipe\n"));
6fcd6f84
ES
2947 lazy_itable_init = 1;
2948 itable_zeroed = 1;
23a1b987 2949 zero_hugefile = 0;
6fcd6f84
ES
2950 }
2951 }
5827d241 2952
6cb27404
TT
2953 if (fs_param.s_flags & EXT2_FLAGS_TEST_FILESYS)
2954 fs->super->s_flags |= EXT2_FLAGS_TEST_FILESYS;
2955
7889640d
DW
2956 if (ext2fs_has_feature_flex_bg(&fs_param) ||
2957 ext2fs_has_feature_huge_file(&fs_param) ||
2958 ext2fs_has_feature_gdt_csum(&fs_param) ||
2959 ext2fs_has_feature_dir_nlink(&fs_param) ||
2960 ext2fs_has_feature_metadata_csum(&fs_param) ||
2961 ext2fs_has_feature_extra_isize(&fs_param))
b7c5b403
TT
2962 fs->super->s_kbytes_written = 1;
2963
e41784eb
TT
2964 /*
2965 * Wipe out the old on-disk superblock
2966 */
04a96857
TT
2967 if (!noaction)
2968 zap_sector(fs, 2, 6);
e41784eb 2969
1e3472c5 2970 /*
b0afdda1 2971 * Parse or generate a UUID for the filesystem
1e3472c5 2972 */
b0afdda1 2973 if (fs_uuid) {
665ebf37
DD
2974 if ((strcasecmp(fs_uuid, "null") == 0) ||
2975 (strcasecmp(fs_uuid, "clear") == 0)) {
2976 uuid_clear(fs->super->s_uuid);
2977 } else if (strcasecmp(fs_uuid, "time") == 0) {
2978 uuid_generate_time(fs->super->s_uuid);
2979 } else if (strcasecmp(fs_uuid, "random") == 0) {
2980 uuid_generate(fs->super->s_uuid);
2981 } else if (uuid_parse(fs_uuid, fs->super->s_uuid) != 0) {
b0afdda1
TT
2982 com_err(device_name, 0, "could not parse UUID: %s\n",
2983 fs_uuid);
2984 exit(1);
2985 }
2986 } else
2987 uuid_generate(fs->super->s_uuid);
1b7623b8
DW
2988
2989 if (ext2fs_has_feature_csum_seed(fs->super))
2990 fs->super->s_checksum_seed = ext2fs_crc32c_le(~0,
2991 fs->super->s_uuid, sizeof(fs->super->s_uuid));
2992
4ffbe3af 2993 ext2fs_init_csum_seed(fs);
1e3472c5 2994
843049c4
TT
2995 /*
2996 * Initialize the directory index variables
2997 */
d5f57d95
TT
2998 hash_alg_str = get_string_from_profile(fs_types, "hash_alg",
2999 "half_md4");
3000 hash_alg = e2p_string2hash(hash_alg_str);
5a2db046 3001 free(hash_alg_str);
d5f57d95
TT
3002 fs->super->s_def_hash_version = (hash_alg >= 0) ? hash_alg :
3003 EXT2_HASH_HALF_MD4;
e1f71006
JQ
3004
3005 if (memcmp(fs_param.s_hash_seed, zero_buf,
3006 sizeof(fs_param.s_hash_seed)) != 0) {
3007 memcpy(fs->super->s_hash_seed, fs_param.s_hash_seed,
3008 sizeof(fs->super->s_hash_seed));
3009 } else
3010 uuid_generate((unsigned char *) fs->super->s_hash_seed);
843049c4 3011
44c09c04 3012 /*
3daf5926
ES
3013 * Periodic checks can be enabled/disabled via config file.
3014 * Note we override the kernel include file's idea of what the default
3015 * check interval (never) should be. It's a good idea to check at
3016 * least *occasionally*, specially since servers will never rarely get
3017 * to reboot, since Linux is so robust these days. :-)
3018 *
3019 * 180 days (six months) seems like a good value.
44c09c04 3020 */
3daf5926
ES
3021#ifdef EXT2_DFL_CHECKINTERVAL
3022#undef EXT2_DFL_CHECKINTERVAL
3023#endif
3024#define EXT2_DFL_CHECKINTERVAL (86400L * 180L)
3025
3026 if (get_bool_from_profile(fs_types, "enable_periodic_fsck", 0)) {
3027 fs->super->s_checkinterval = EXT2_DFL_CHECKINTERVAL;
3028 fs->super->s_max_mnt_count = EXT2_DFL_MAX_MNT_COUNT;
3029 /*
3030 * Add "jitter" to the superblock's check interval so that we
3031 * don't check all the filesystems at the same time. We use a
3032 * kludgy hack of using the UUID to derive a random jitter value
3033 */
3034 for (i = 0, val = 0 ; i < sizeof(fs->super->s_uuid); i++)
3035 val += fs->super->s_uuid[i];
3036 fs->super->s_max_mnt_count += val % EXT2_DFL_MAX_MNT_COUNT;
14b283ae
TT
3037 } else
3038 fs->super->s_max_mnt_count = -1;
44c09c04 3039
1e3472c5
TT
3040 /*
3041 * Override the creator OS, if applicable
3042 */
3043 if (creator_os && !set_os(fs->super, creator_os)) {
d9c56d3c 3044 com_err (program_name, 0, _("unknown os - %s"), creator_os);
1e3472c5
TT
3045 exit(1);
3046 }
3047
4ea0a110
TT
3048 /*
3049 * For the Hurd, we will turn off filetype since it doesn't
3050 * support it.
3051 */
3052 if (fs->super->s_creator_os == EXT2_OS_HURD)
7889640d 3053 ext2fs_clear_feature_filetype(fs->super);
4ea0a110 3054
1e3472c5
TT
3055 /*
3056 * Set the volume label...
3057 */
3058 if (volume_label) {
ef9abe5f
TT
3059 memset(fs->super->s_volume_name, 0,
3060 sizeof(fs->super->s_volume_name));
3061 strncpy(fs->super->s_volume_name, volume_label,
3062 sizeof(fs->super->s_volume_name));
1e3472c5
TT
3063 }
3064
3065 /*
3066 * Set the last mount directory
3067 */
3068 if (mount_dir) {
ef9abe5f
TT
3069 memset(fs->super->s_last_mounted, 0,
3070 sizeof(fs->super->s_last_mounted));
3071 strncpy(fs->super->s_last_mounted, mount_dir,
3072 sizeof(fs->super->s_last_mounted));
1e3472c5 3073 }
efc6f628 3074
bbb85949
IM
3075 /* Set current default encryption algorithms for data and
3076 * filename encryption */
7889640d 3077 if (ext2fs_has_feature_encrypt(fs->super)) {
bbb85949
IM
3078 fs->super->s_encrypt_algos[0] =
3079 EXT4_ENCRYPTION_MODE_AES_256_XTS;
3080 fs->super->s_encrypt_algos[1] =
f7257a93 3081 EXT4_ENCRYPTION_MODE_AES_256_CTS;
bbb85949
IM
3082 }
3083
7889640d 3084 if (ext2fs_has_feature_metadata_csum(fs->super))
53c2c8af
DW
3085 fs->super->s_checksum_type = EXT2_CRC32C_CHKSUM;
3086
50787ea2 3087 if (!quiet || noaction)
3839e657
TT
3088 show_stats(fs);
3089
50787ea2
TT
3090 if (noaction)
3091 exit(0);
3092
7889640d 3093 if (ext2fs_has_feature_journal_dev(fs->super)) {
16ed5b3a 3094 create_journal_dev(fs);
7a8f4973 3095 printf("\n");
47fee2ef 3096 exit(ext2fs_close_free(&fs) ? 1 : 0);
16ed5b3a
TT
3097 }
3098
3839e657
TT
3099 if (bad_blocks_filename)
3100 read_bb_file(fs, &bb_list, bad_blocks_filename);
3101 if (cflag)
3102 test_disk(fs, &bb_list);
3839e657 3103 handle_bad_blocks(fs, bb_list);
65c6c3e0 3104
0c17cb25 3105 fs->stride = fs_stride = fs->super->s_raid_stride;
95fd65bb 3106 if (!quiet)
45ff69ff 3107 printf("%s", _("Allocating group tables: "));
7889640d 3108 if (ext2fs_has_feature_flex_bg(fs->super) &&
3c6e91c5
TT
3109 packed_meta_blocks)
3110 retval = packed_allocate_tables(fs);
3111 else
3112 retval = ext2fs_allocate_tables(fs);
19c78dc0 3113 if (retval) {
45ff69ff 3114 com_err(program_name, retval, "%s",
d9c56d3c 3115 _("while trying to allocate filesystem tables"));
19c78dc0
TT
3116 exit(1);
3117 }
95fd65bb 3118 if (!quiet)
45ff69ff 3119 printf("%s", _("done \n"));
c6ed60cd
TT
3120
3121 retval = ext2fs_convert_subcluster_bitmap(fs, &fs->block_map);
3122 if (retval) {
45ff69ff 3123 com_err(program_name, retval, "%s",
c6ed60cd
TT
3124 _("\n\twhile converting subcluster bitmap"));
3125 exit(1);
3126 }
3127
f3db3566 3128 if (super_only) {
a6eeac1c
AD
3129 check_plausibility(device_name, CHECK_FS_EXIST, NULL);
3130 printf(_("%s may be further corrupted by superblock rewrite\n"),
3131 device_name);
3132 if (!force)
3133 proceed_question(proceed_delay);
f3db3566
TT
3134 fs->super->s_state |= EXT2_ERROR_FS;
3135 fs->flags &= ~(EXT2_FLAG_IB_DIRTY|EXT2_FLAG_BB_DIRTY);
a6eeac1c 3136 /*
ba9e0afc
TT
3137 * The command "mke2fs -S" is used to recover
3138 * corrupted file systems, so do not mark any of the
3139 * inodes as unused; we want e2fsck to consider all
3140 * inodes as potentially containing recoverable data.
3141 */
ef5b606c 3142 if (ext2fs_has_group_desc_csum(fs)) {
30ac1ce7 3143 for (i = 0; i < fs->group_desc_count; i++)
ba9e0afc
TT
3144 ext2fs_bg_itable_unused_set(fs, i, 0);
3145 }
f3db3566 3146 } else {
59f27247 3147 /* rsv must be a power of two (64kB is MD RAID sb alignment) */
02d6f47e
JS
3148 blk64_t rsv = 65536 / fs->blocksize;
3149 blk64_t blocks = ext2fs_blocks_count(fs->super);
3150 blk64_t start;
3151 blk64_t ret_blk;
1400bbb6
TT
3152
3153#ifdef ZAP_BOOTBLOCK
04a96857 3154 zap_sector(fs, 0, 2);
1400bbb6 3155#endif
59f27247 3156
1400bbb6
TT
3157 /*
3158 * Wipe out any old MD RAID (or other) metadata at the end
3159 * of the device. This will also verify that the device is
59f27247 3160 * as large as we think. Be careful with very small devices.
1400bbb6 3161 */
59f27247
AD
3162 start = (blocks & ~(rsv - 1));
3163 if (start > rsv)
3164 start -= rsv;
3165 if (start > 0)
02d6f47e 3166 retval = ext2fs_zero_blocks2(fs, start, blocks - start,
b626b39a 3167 &ret_blk, NULL);
59f27247 3168
1400bbb6
TT
3169 if (retval) {
3170 com_err(program_name, retval,
02d6f47e 3171 _("while zeroing block %llu at end of filesystem"),
1400bbb6 3172 ret_blk);
1400bbb6 3173 }
6fcd6f84 3174 write_inode_tables(fs, lazy_itable_init, itable_zeroed);
f3db3566
TT
3175 create_root_dir(fs);
3176 create_lost_and_found(fs);
3177 reserve_inodes(fs);
3178 create_bad_block_inode(fs, bb_list);
7889640d 3179 if (ext2fs_has_feature_resize_inode(fs->super)) {
ea774315
TT
3180 retval = ext2fs_create_resize_inode(fs);
3181 if (retval) {
3182 com_err("ext2fs_create_resize_inode", retval,
45ff69ff 3183 "%s",
d323f8fb 3184 _("while reserving blocks for online resize"));
ea774315
TT
3185 exit(1);
3186 }
d323f8fb 3187 }
f3db3566 3188 }
8ddaa66b 3189
16ed5b3a
TT
3190 if (journal_device) {
3191 ext2_filsys jfs;
efc6f628 3192
d69f43f5
TT
3193 if (!check_plausibility(journal_device, CHECK_BLOCK_DEV,
3194 NULL) && !force)
f83f4132 3195 proceed_question(proceed_delay);
63985320 3196 check_mount(journal_device, force, _("journal"));
8ddaa66b 3197
16ed5b3a
TT
3198 retval = ext2fs_open(journal_device, EXT2_FLAG_RW|
3199 EXT2_FLAG_JOURNAL_DEV_OK, 0,
3200 fs->blocksize, unix_io_manager, &jfs);
3201 if (retval) {
3202 com_err(program_name, retval,
3203 _("while trying to open journal device %s\n"),
3204 journal_device);
3205 exit(1);
3206 }
93345d15 3207 if (!quiet) {
efc6f628 3208 printf(_("Adding journal to device %s: "),
8ddaa66b 3209 journal_device);
93345d15
TT
3210 fflush(stdout);
3211 }
16ed5b3a
TT
3212 retval = ext2fs_add_journal_device(fs, jfs);
3213 if(retval) {
efc6f628
TT
3214 com_err (program_name, retval,
3215 _("\n\twhile trying to add journal to device %s"),
8ddaa66b
TT
3216 journal_device);
3217 exit(1);
3218 }
3219 if (!quiet)
45ff69ff 3220 printf("%s", _("done\n"));
47fee2ef 3221 ext2fs_close_free(&jfs);
2d15576d 3222 free(journal_device);
9dc6ad1e 3223 } else if ((journal_size) ||
7889640d 3224 ext2fs_has_feature_journal(&fs_param)) {
a620badd 3225 if (super_only) {
45ff69ff 3226 printf("%s", _("Skipping journal creation in super-only mode\n"));
a620badd
TT
3227 fs->super->s_journal_inum = EXT2_JOURNAL_INO;
3228 goto no_journal;
3229 }
3230
93345d15 3231 if (!journal_blocks) {
7889640d 3232 ext2fs_clear_feature_journal(fs->super);
93345d15
TT
3233 goto no_journal;
3234 }
3235 if (!quiet) {
d4e0b1c6 3236 printf(_("Creating journal (%u blocks): "),
16ad3334 3237 journal_blocks);
93345d15
TT
3238 fflush(stdout);
3239 }
b818205f
TT
3240 retval = ext2fs_add_journal_inode2(fs, journal_blocks,
3241 journal_location,
3242 journal_flags);
85ef4ae8 3243 if (retval) {
45ff69ff
AD
3244 com_err(program_name, retval, "%s",
3245 _("\n\twhile trying to create journal"));
85ef4ae8
TT
3246 exit(1);
3247 }
3248 if (!quiet)
45ff69ff 3249 printf("%s", _("done\n"));
85ef4ae8 3250 }
93345d15 3251no_journal:
0f5eba75 3252 if (!super_only &&
7889640d 3253 ext2fs_has_feature_mmp(fs->super)) {
0f5eba75
AD
3254 retval = ext2fs_mmp_init(fs);
3255 if (retval) {
45ff69ff
AD
3256 fprintf(stderr, "%s",
3257 _("\nError while enabling multiple "
3258 "mount protection feature."));
0f5eba75
AD
3259 exit(1);
3260 }
3261 if (!quiet)
3262 printf(_("Multiple mount protection is enabled "
3263 "with update interval %d seconds.\n"),
3264 fs->super->s_mmp_update_interval);
3265 }
93345d15 3266
7889640d 3267 if (ext2fs_has_feature_bigalloc(&fs_param))
c6ed60cd 3268 fix_cluster_bg_counts(fs);
7889640d 3269 if (ext2fs_has_feature_quota(&fs_param))
1f5d7a89
AK
3270 create_quota_inodes(fs);
3271
c42de75b 3272 retval = mk_hugefiles(fs, device_name);
23a1b987
TT
3273 if (retval)
3274 com_err(program_name, retval, "while creating huge files");
217c0bdf 3275 /* Copy files from the specified directory */
0f267471 3276 if (src_root_dir) {
217c0bdf
RY
3277 if (!quiet)
3278 printf("%s", _("Copying files into the device: "));
3279
0f267471 3280 retval = populate_fs(fs, EXT2_ROOT_INO, src_root_dir,
a3111e80 3281 EXT2_ROOT_INO);
2af02215
RY
3282 if (retval) {
3283 com_err(program_name, retval, "%s",
b04af4fe 3284 _("while populating file system"));
2af02215
RY
3285 exit(1);
3286 } else if (!quiet)
217c0bdf
RY
3287 printf("%s", _("done\n"));
3288 }
23a1b987 3289
3839e657 3290 if (!quiet)
45ff69ff 3291 printf("%s", _("Writing superblocks and "
d9c56d3c 3292 "filesystem accounting information: "));
faa2dcda
LC
3293 checkinterval = fs->super->s_checkinterval;
3294 max_mnt_count = fs->super->s_max_mnt_count;
47fee2ef 3295 retval = ext2fs_close_free(&fs);
5d45d803 3296 if (retval) {
45ff69ff 3297 fprintf(stderr, "%s",
025d31b1 3298 _("\nWarning, had trouble writing out superblocks.\n"));
faa2dcda 3299 } else if (!quiet) {
45ff69ff 3300 printf("%s", _("done\n\n"));
1cca86f5 3301 if (!getenv("MKE2FS_SKIP_CHECK_MSG"))
faa2dcda 3302 print_check_message(max_mnt_count, checkinterval);
93345d15 3303 }
faa2dcda 3304
a6d8302b
TT
3305 remove_error_table(&et_ext2_error_table);
3306 remove_error_table(&et_prof_error_table);
3d43836f 3307 profile_release(profile);
5a2db046
TT
3308 for (i=0; fs_types[i]; i++)
3309 free(fs_types[i]);
3310 free(fs_types);
faa2dcda 3311 return retval;
3839e657 3312}