#include <fcntl.h>
#include <ctype.h>
#include <time.h>
-#ifdef linux
+#ifdef __linux__
#include <sys/utsname.h>
#endif
#ifdef HAVE_GETOPT_H
#include <sys/ioctl.h>
#include <sys/types.h>
-#include <linux/ext2_fs.h>
-
+#include "ext2fs/ext2_fs.h"
#include "et/com_err.h"
#include "uuid/uuid.h"
#include "e2p/e2p.h"
char *journal_device;
int sync_kludge; /* Set using the MKE2FS_SYNC env. option */
+int sys_page_size = 4096;
+
static void usage(void)
{
fprintf(stderr, _("Usage: %s [-c|-t|-l filename] [-b block-size] "
" [-N number-of-inodes]\n\t[-m reserved-blocks-percentage] "
"[-o creator-os] [-g blocks-per-group]\n\t[-L volume-label] "
"[-M last-mounted-directory] [-O feature[,...]]\n\t"
- "[-r fs-revision] [-R raid_opts] [-s sparse-super-flag]\n\t"
- "[-qvSV] device [blocks-count]\n"),
+ "[-r fs-revision] [-R raid_opts] [-qvSV] device [blocks-count]\n"),
program_name);
exit(1);
}
* of zero meaning that it is the default parameter for the type.
* Note that order is important in the table below.
*/
+#define DEF_MAX_BLOCKSIZE -1
static char default_str[] = "default";
struct mke2fs_defaults {
const char *type;
{ default_str, 3, 1024, 8192 },
{ "journal", 0, 4096, 8192 },
{ "news", 0, 4096, 4096 },
- { "largefile", 0, 4096, 1024 * 1024 },
- { "largefile4", 0, 4096, 4096 * 1024 },
+ { "largefile", 0, DEF_MAX_BLOCKSIZE, 1024 * 1024 },
+ { "largefile4", 0, DEF_MAX_BLOCKSIZE, 4096 * 1024 },
{ 0, 0, 0, 0},
};
-static void set_fs_defaults(char *fs_type, struct ext2_super_block *super,
+static void set_fs_defaults(const char *fs_type,
+ struct ext2_super_block *super,
int blocksize, int *inode_ratio)
{
int megs;
int ratio = 0;
struct mke2fs_defaults *p;
- megs = (super->s_blocks_count * (EXT2_BLOCK_SIZE(super) / 1024) /
- 1024);
+ megs = super->s_blocks_count * (EXT2_BLOCK_SIZE(super) / 1024) / 1024;
if (inode_ratio)
ratio = *inode_ratio;
if (!fs_type)
(megs > p->size))
continue;
if (ratio == 0)
- *inode_ratio = p->inode_ratio;
+ *inode_ratio = p->inode_ratio < blocksize ?
+ blocksize : p->inode_ratio;
if (blocksize == 0) {
+ if (p->blocksize == DEF_MAX_BLOCKSIZE)
+ p->blocksize = sys_page_size;
super->s_log_frag_size = super->s_log_block_size =
int_log2(p->blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
}
*/
static void invalid_block(ext2_filsys fs, blk_t blk)
{
- printf(_("Bad block %u out of range; ignored.\n"), blk);
+ fprintf(stderr, _("Bad block %u out of range; ignored.\n"), blk);
return;
}
errcode_t retval;
char buf[1024];
- sprintf(buf, "badblocks -b %d %s%s %d", fs->blocksize,
- quiet ? "" : "-s ", fs->device_name,
- fs->super->s_blocks_count);
+ sprintf(buf, "badblocks -b %d %s%s%s %d", fs->blocksize,
+ quiet ? "" : "-s ", (cflag > 1) ? "-w " : "",
+ fs->device_name, fs->super->s_blocks_count);
if (verbose)
printf(_("Running command: %s\n"), buf);
f = popen(buf, "r");
*/
must_be_good = fs->super->s_first_data_block + 1 + fs->desc_blocks;
for (i = fs->super->s_first_data_block; i <= must_be_good; i++) {
- if (badblocks_list_test(bb_list, i)) {
+ if (ext2fs_badblocks_list_test(bb_list, i)) {
fprintf(stderr, _("Block %d in primary "
"superblock/group descriptor area bad.\n"), i);
fprintf(stderr, _("Blocks %d through %d must be good "
for (i = 1; i < fs->group_desc_count; i++) {
group_bad = 0;
for (j=0; j < fs->desc_blocks+1; j++) {
- if (badblocks_list_test(bb_list, group_block +
- j)) {
+ if (ext2fs_badblocks_list_test(bb_list,
+ group_block + j)) {
if (!group_bad)
fprintf(stderr,
_("Warning: the backup superblock/group descriptors at block %d contain\n"
/*
* Mark all the bad blocks as used...
*/
- retval = badblocks_list_iterate_begin(bb_list, &bb_iter);
+ retval = ext2fs_badblocks_list_iterate_begin(bb_list, &bb_iter);
if (retval) {
- com_err("badblocks_list_iterate_begin", retval,
+ com_err("ext2fs_badblocks_list_iterate_begin", retval,
_("while marking bad blocks as used"));
exit(1);
}
- while (badblocks_list_iterate(bb_iter, &blk))
+ while (ext2fs_badblocks_list_iterate(bb_iter, &blk))
ext2fs_mark_block_bitmap(fs->block_map, blk);
- badblocks_list_iterate_end(bb_iter);
+ ext2fs_badblocks_list_iterate_end(bb_iter);
}
/*
};
static void progress_init(struct progress_struct *progress,
- char *label,__u32 max)
+ const char *label,__u32 max)
{
int i;
retval = zero_blocks(fs, blk, num, 0, &blk, &num);
if (retval) {
- printf(_("\nCould not write %d blocks "
- "in inode table starting at %d: %s\n"),
- num, blk, error_message(retval));
+ fprintf(stderr, _("\nCould not write %d blocks "
+ "in inode table starting at %d: %s\n"),
+ num, blk, error_message(retval));
exit(1);
}
if (sync_kludge) {
int i;
int lpf_size = 0;
+ fs->umask = 077;
retval = ext2fs_mkdir(fs, EXT2_ROOT_INO, 0, name);
if (retval) {
com_err("ext2fs_mkdir", retval,
_("while expanding /lost+found"));
exit(1);
}
- }
+ }
}
static void create_bad_block_inode(ext2_filsys fs, badblocks_list bb_list)
ext2fs_mark_ib_dirty(fs);
}
-static void zap_sector(ext2_filsys fs, int sect)
+#define BSD_DISKMAGIC (0x82564557UL) /* The disk magic number */
+#define BSD_MAGICDISK (0x57455682UL) /* The disk magic number reversed */
+#define BSD_LABEL_OFFSET 64
+
+static void zap_sector(ext2_filsys fs, int sect, int nsect)
{
- char buf[512];
+ char *buf;
int retval;
+ unsigned int *magic;
+
+ buf = malloc(512*nsect);
+ if (!buf) {
+ printf(_("Out of memory erasing sectors %d-%d\n"),
+ sect, sect + nsect - 1);
+ exit(1);
+ }
+ memset(buf, 0, 512*nsect);
+
+ if (sect == 0) {
+ /* Check for a BSD disklabel, and don't erase it if so */
+ retval = io_channel_read_blk(fs->io, 0, -512, buf);
+ if (retval)
+ fprintf(stderr,
+ _("Warning: could not read block 0: %s\n"),
+ error_message(retval));
+ else {
+ magic = (unsigned int *) (buf + BSD_LABEL_OFFSET);
+ if ((*magic == BSD_DISKMAGIC) ||
+ (*magic == BSD_MAGICDISK))
+ return;
+ }
+ }
- memset(buf, 0, 512);
-
io_channel_set_blksize(fs->io, 512);
- retval = io_channel_write_blk(fs->io, sect, -512, buf);
+ retval = io_channel_write_blk(fs->io, sect, -512*nsect, buf);
io_channel_set_blksize(fs->io, fs->blocksize);
+ free(buf);
if (retval)
- printf(_("Warning: could not erase sector %d: %s\n"), sect,
- error_message(retval));
+ fprintf(stderr, _("Warning: could not erase sector %d: %s\n"),
+ sect, error_message(retval));
}
static void create_journal_dev(ext2_filsys fs)
blk_t blk;
int count;
+ retval = ext2fs_create_journal_superblock(fs,
+ fs->super->s_blocks_count, 0, &buf);
+ if (retval) {
+ com_err("create_journal_dev", retval,
+ _("while initializing journal superblock"));
+ exit(1);
+ }
if (quiet)
memset(&progress, 0, sizeof(progress));
else
&progress, &blk, &count);
if (retval) {
com_err("create_journal_dev", retval,
- "while zeroing journal device (block %u, count %d",
+ _("while zeroing journal device (block %u, count %d)"),
blk, count);
exit(1);
}
zero_blocks(0, 0, 0, 0, 0, 0);
- retval = ext2fs_create_journal_superblock(fs,
- fs->super->s_blocks_count, 0, &buf);
- if (retval) {
- com_err("create_journal_dev", retval,
- _("while initialization journal superblock"));
- exit(1);
- }
retval = io_channel_write_blk(fs->io,
fs->super->s_first_data_block+1,
1, buf);
int i, need, col_left;
if (param.s_blocks_count != s->s_blocks_count)
- printf(_("warning: %d blocks unused.\n\n"),
+ fprintf(stderr, _("warning: %d blocks unused.\n\n"),
param.s_blocks_count - s->s_blocks_count);
memset(buf, 0, sizeof(buf));
blk_t group_blk_max = 8192;
int blocksize = 0;
int inode_ratio = 0;
+ int inode_size = 0;
int reserved_ratio = 5;
ext2_ino_t num_inodes = 0;
errcode_t retval;
- int sparse_option = 1;
char * oldpath = getenv("PATH");
char * raid_opts = 0;
- char * fs_type = 0;
- const char * feature_set = "filetype";
+ const char * fs_type = 0;
+ int default_features = 1;
blk_t dev_size;
-#ifdef linux
+#ifdef __linux__
struct utsname ut;
-
- if (uname(&ut)) {
- perror("uname");
- exit(1);
- }
- if ((ut.release[0] == '1') ||
- (ut.release[0] == '2' && ut.release[1] == '.' &&
- ut.release[2] < '2' && ut.release[3] == '.'))
- feature_set = NULL;
#endif
+ long sysval;
+
/* Update our PATH to include /sbin */
if (oldpath) {
char *newpath;
tmp = getenv("MKE2FS_SYNC");
if (tmp)
sync_kludge = atoi(tmp);
+
+ /* Determine the system page size if possible */
+#ifdef HAVE_SYSCONF
+#if (!defined(_SC_PAGESIZE) && defined(_SC_PAGE_SIZE))
+#define _SC_PAGESIZE _SC_PAGE_SIZE
+#endif
+#ifdef _SC_PAGESIZE
+ sysval = sysconf(_SC_PAGESIZE);
+ if (sysval > 0)
+ sys_page_size = sysval;
+#endif /* _SC_PAGESIZE */
+#endif /* HAVE_SYSCONF */
setbuf(stdout, NULL);
setbuf(stderr, NULL);
initialize_ext2_error_table();
memset(¶m, 0, sizeof(struct ext2_super_block));
param.s_rev_level = 1; /* Create revision 1 filesystems now */
-
- fprintf (stderr, _("mke2fs %s, %s for EXT2 FS %s, %s\n"),
- E2FSPROGS_VERSION, E2FSPROGS_DATE,
- EXT2FS_VERSION, EXT2FS_DATE);
- if (argc && *argv)
- program_name = *argv;
+ param.s_feature_incompat |= EXT2_FEATURE_INCOMPAT_FILETYPE;
+ param.s_feature_ro_compat |= EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
+
+#ifdef __linux__
+ if (uname(&ut)) {
+ perror("uname");
+ exit(1);
+ }
+ if ((ut.release[0] == '1') ||
+ (ut.release[0] == '2' && ut.release[1] == '.' &&
+ ut.release[2] < '2' && ut.release[3] == '.')) {
+ param.s_rev_level = 0;
+ param.s_feature_incompat = 0;
+ param.s_feature_compat = 0;
+ param.s_feature_ro_compat = 0;
+ }
+#endif
+ fprintf (stderr, "mke2fs %s (%s)\n",
+ E2FSPROGS_VERSION, E2FSPROGS_DATE);
+
+ if (argc && *argv) {
+ program_name = get_progname(*argv);
+
+ /* If called as mkfs.ext3, create a journal inode */
+ if (!strcmp(program_name, "mkfs.ext3"))
+ journal_size = -1;
+ }
+
while ((c = getopt (argc, argv,
"b:cf:g:i:jl:m:no:qr:R:s:tvI:J:ST:FL:M:N:O:V")) != EOF)
switch (c) {
case 'b':
blocksize = strtoul(optarg, &tmp, 0);
- if (blocksize < 1024 || blocksize > 4096 || *tmp) {
+ if (blocksize < EXT2_MIN_BLOCK_SIZE ||
+ blocksize > EXT2_MAX_BLOCK_SIZE || *tmp) {
com_err(program_name, 0,
_("bad block size - %s"), optarg);
exit(1);
}
+ if (blocksize > 4096)
+ fprintf(stderr, _("Warning: blocksize %d not "
+ "usable on most systems.\n"),
+ blocksize);
param.s_log_block_size =
int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
group_blk_max = blocksize * 8;
break;
- case 'c':
- case 't': /* Check for bad blocks */
- cflag = 1;
+ case 'c': /* Check for bad blocks */
+ case 't': /* deprecated */
+ cflag++;
break;
case 'f':
size = strtoul(optarg, &tmp, 0);
- if (size < 1024 || size > 4096 || *tmp) {
+ if (size < EXT2_MIN_BLOCK_SIZE ||
+ size > EXT2_MAX_BLOCK_SIZE || *tmp) {
com_err(program_name, 0,
_("bad fragment size - %s"),
optarg);
}
param.s_log_frag_size =
int_log2(size >> EXT2_MIN_BLOCK_LOG_SIZE);
- printf(_("Warning: fragments not supported. "
+ fprintf(stderr, _("Warning: fragments not supported. "
"Ignoring -f option\n"));
break;
case 'g':
break;
case 'i':
inode_ratio = strtoul(optarg, &tmp, 0);
- if (inode_ratio < 1024 || inode_ratio > 4096 * 1024 ||
+ if (inode_ratio < EXT2_MIN_BLOCK_SIZE ||
+ inode_ratio > EXT2_MAX_BLOCK_SIZE * 1024 ||
*tmp) {
com_err(program_name, 0,
- _("bad inode ratio - %s"), optarg);
+ _("bad inode ratio %s (min %d/max %d"),
+ optarg, EXT2_MIN_BLOCK_SIZE,
+ EXT2_MAX_BLOCK_SIZE);
exit(1);
}
break;
parse_journal_opts(optarg);
break;
case 'j':
+ param.s_feature_compat |=
+ EXT3_FEATURE_COMPAT_HAS_JOURNAL;
if (!journal_size)
journal_size = -1;
break;
break;
case 'r':
param.s_rev_level = atoi(optarg);
+ if (param.s_rev_level == EXT2_GOOD_OLD_REV) {
+ param.s_feature_incompat = 0;
+ param.s_feature_compat = 0;
+ param.s_feature_ro_compat = 0;
+ }
break;
- case 's':
- sparse_option = atoi(optarg);
+ case 's': /* deprecated */
+ if (atoi(optarg))
+ param.s_feature_ro_compat |=
+ EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
+ else
+ param.s_feature_ro_compat &=
+ ~EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
break;
#ifdef EXT2_DYNAMIC_REV
case 'I':
- param.s_inode_size = atoi(optarg);
+ inode_size = strtoul(optarg, &tmp, 0);
+ if (*tmp) {
+ com_err(program_name, 0,
+ _("bad inode size - %s"), optarg);
+ exit(1);
+ }
break;
#endif
case 'N':
mount_dir = optarg;
break;
case 'O':
- feature_set = optarg;
+ if (!strcmp(optarg, "none") || default_features) {
+ param.s_feature_compat = 0;
+ param.s_feature_incompat = 0;
+ param.s_feature_ro_compat = 0;
+ default_features = 0;
+ }
+ if (!strcmp(optarg, "none"))
+ break;
+ if (e2p_edit_feature(optarg,
+ ¶m.s_feature_compat,
+ ok_features)) {
+ fprintf(stderr,
+ _("Invalid filesystem option set: %s\n"), optarg);
+ exit(1);
+ }
break;
case 'R':
raid_opts = optarg;
if (raid_opts)
parse_raid_opts(raid_opts);
- /* Parse the user-supplied feature_set, if any. */
- if (feature_set && !strncasecmp(feature_set, "none", 4))
- feature_set = NULL;
- if (feature_set && e2p_edit_feature(feature_set,
- ¶m.s_feature_compat,
- ok_features)) {
- fprintf(stderr, _("Invalid filesystem option set: %s\n"),
- feature_set);
- exit(1);
+ /*
+ * If there's no blocksize specified and there is a journal
+ * device, use it to figure out the blocksize
+ */
+ if (blocksize == 0 && journal_device) {
+ ext2_filsys jfs;
+
+ retval = ext2fs_open(journal_device,
+ EXT2_FLAG_JOURNAL_DEV_OK, 0,
+ 0, unix_io_manager, &jfs);
+ if (retval) {
+ com_err(program_name, retval,
+ _("while trying to open journal device %s\n"),
+ journal_device);
+ exit(1);
+ }
+ blocksize = jfs->blocksize;
+ param.s_log_block_size =
+ int_log2(blocksize >> EXT2_MIN_BLOCK_LOG_SIZE);
+ ext2fs_close(jfs);
}
+ if (blocksize > sys_page_size) {
+ if (!force) {
+ com_err(program_name, 0,
+ _("%d-byte blocks too big for system (max %d)"),
+ blocksize, sys_page_size);
+ proceed_question();
+ }
+ fprintf(stderr, _("Warning: %d-byte blocks too big for system "
+ "(max %d), forced to continue\n"),
+ blocksize, sys_page_size);
+ }
+
+ if (param.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
+ if (!fs_type)
+ fs_type = "journal";
+ reserved_ratio = 0;
+ param.s_feature_incompat = EXT3_FEATURE_INCOMPAT_JOURNAL_DEV;
+ param.s_feature_compat = 0;
+ param.s_feature_ro_compat = 0;
+ }
+ if (param.s_rev_level == EXT2_GOOD_OLD_REV &&
+ (param.s_feature_compat || param.s_feature_ro_compat ||
+ param.s_feature_incompat))
+ param.s_rev_level = 1; /* Create a revision 1 filesystem */
+
if (!force)
check_plausibility(device_name);
check_mount(device_name, force, _("filesystem"));
if ((param.s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
!journal_size)
journal_size = -1;
- if (!fs_type &&
- (param.s_feature_incompat & EXT3_FEATURE_INCOMPAT_JOURNAL_DEV))
- fs_type = "journal";
+
set_fs_defaults(fs_type, ¶m, blocksize, &inode_ratio);
if (param.s_blocks_per_group) {
}
}
+ if (inode_size) {
+ if (inode_size < EXT2_GOOD_OLD_INODE_SIZE ||
+ inode_size > EXT2_BLOCK_SIZE(¶m) ||
+ inode_size & (inode_size - 1)) {
+ com_err(program_name, 0,
+ _("bad inode size %d (min %d/max %d)"),
+ inode_size, EXT2_GOOD_OLD_INODE_SIZE,
+ EXT2_BLOCK_SIZE(¶m));
+ exit(1);
+ }
+ if (inode_size != EXT2_GOOD_OLD_INODE_SIZE)
+ fprintf(stderr, _("Warning: %d-byte inodes not usable "
+ "on most systems\n"),
+ inode_size);
+ param.s_inode_size = inode_size;
+ }
+
/*
* Calculate number of inodes based on the inode ratio
*/
*/
param.s_r_blocks_count = (param.s_blocks_count * reserved_ratio) / 100;
- /* Turn off features not supported by the earlier filesystem version */
- if (param.s_rev_level == 0) {
- sparse_option = 0;
- feature_set = NULL;
- }
- if (sparse_option)
- param.s_feature_ro_compat |=
- EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER;
-
}
int main (int argc, char *argv[])
#ifdef ENABLE_NLS
setlocale(LC_MESSAGES, "");
+ setlocale(LC_CTYPE, "");
bindtextdomain(NLS_CAT_NAME, LOCALEDIR);
textdomain(NLS_CAT_NAME);
#endif
/*
* Wipe out the old on-disk superblock
*/
- zap_sector(fs, 2);
+ if (!noaction)
+ zap_sector(fs, 2, 6);
/*
* Generate a UUID for it...
if (fs->super->s_feature_incompat &
EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) {
create_journal_dev(fs);
- ext2fs_close(fs);
- exit(0);
+ exit(ext2fs_close(fs) ? 1 : 0);
}
if (bad_blocks_filename)
fs->super->s_state |= EXT2_ERROR_FS;
fs->flags &= ~(EXT2_FLAG_IB_DIRTY|EXT2_FLAG_BB_DIRTY);
} else {
+ /* rsv must be a power of two (64kB is MD RAID sb alignment) */
+ int rsv = 65536 / fs->blocksize;
+ unsigned long blocks = fs->super->s_blocks_count;
+ unsigned long start;
+ blk_t ret_blk;
+
+#ifdef ZAP_BOOTBLOCK
+ zap_sector(fs, 0, 2);
+#endif
+
+ /*
+ * Wipe out any old MD RAID (or other) metadata at the end
+ * of the device. This will also verify that the device is
+ * as large as we think. Be careful with very small devices.
+ */
+ start = (blocks & ~(rsv - 1));
+ if (start > rsv)
+ start -= rsv;
+ if (start > 0)
+ retval = zero_blocks(fs, start, blocks - start,
+ NULL, &ret_blk, NULL);
+
+ if (retval) {
+ com_err(program_name, retval,
+ _("zeroing block %u at end of filesystem"),
+ ret_blk);
+ exit(1);
+ }
write_inode_tables(fs);
create_root_dir(fs);
create_lost_and_found(fs);
reserve_inodes(fs);
create_bad_block_inode(fs, bb_list);
-#ifdef ZAP_BOOTBLOCK
- zap_sector(fs, 0);
-#endif
}
if (journal_device) {
exit(1);
}
if (!quiet) {
- printf(_("Creating journal on device %s: "),
+ printf(_("Adding journal to device %s: "),
journal_device);
fflush(stdout);
}
retval = ext2fs_add_journal_device(fs, jfs);
if(retval) {
com_err (program_name, retval,
- _("while trying to add journal to device %s"),
+ _("\n\twhile trying to add journal to device %s"),
journal_device);
exit(1);
}
if (!quiet)
printf(_("done\n"));
ext2fs_close(jfs);
+ free(journal_device);
} else if (journal_size) {
journal_blocks = figure_journal_size(journal_size, fs);
journal_flags);
if (retval) {
com_err (program_name, retval,
- _("while trying to create journal"));
+ _("\n\twhile trying to create journal"));
exit(1);
}
if (!quiet)
"filesystem accounting information: "));
retval = ext2fs_flush(fs);
if (retval) {
- printf(_("\nWarning, had trouble writing out superblocks."));
+ fprintf(stderr,
+ _("\nWarning, had trouble writing out superblocks."));
}
if (!quiet) {
printf(_("done\n\n"));
- printf(_("Filesystem will be checked run "
- "every %d mounts or %g days.\n"),
- fs->super->s_max_mnt_count,
- (double)fs->super->s_checkinterval / (3600 * 24));
+ print_check_message(fs);
}
- ext2fs_close(fs);
- return 0;
+ val = ext2fs_close(fs);
+ return (retval || val) ? 1 : 0;
}