X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=misc%2Fmke2fs.c;h=0f5f1e097e27acba43fb80575f5452cc74e2136f;hb=f9e4abf71430bbdf8f61190a420906fb604f0f74;hp=7f5e5e5eb8dc26e9546ca1df489510ed47a7cffa;hpb=7d5633cf6ee1be74777cf4b1adfa9738ff33f2b7;p=tools%2Fe2fsprogs.git diff --git a/misc/mke2fs.c b/misc/mke2fs.c index 7f5e5e5..0f5f1e0 100644 --- a/misc/mke2fs.c +++ b/misc/mke2fs.c @@ -19,10 +19,15 @@ #include #include #include -#include #include +#ifdef __linux__ +#include +#endif #ifdef HAVE_GETOPT_H #include +#else +extern char *optarg; +extern int optind; #endif #ifdef HAVE_UNISTD_H #include @@ -38,27 +43,19 @@ #endif #include #include -#include - -#ifdef HAVE_LINUX_FS_H -#include -#endif -#include -#ifdef HAVE_LINUX_MAJOR_H -#include -#endif +#include "ext2fs/ext2_fs.h" #include "et/com_err.h" #include "uuid/uuid.h" +#include "e2p/e2p.h" #include "ext2fs/ext2fs.h" +#include "util.h" #include "../version.h" - -/* Everything is STDC, these days */ -#define NOARGS void +#include "nls-enable.h" #define STRIDE_LENGTH 8 -#ifndef sparc +#ifndef __sparc__ #define ZAP_BOOTBLOCK #endif @@ -66,37 +63,42 @@ extern int isatty(int); extern FILE *fpopen(const char *cmd, const char *mode); const char * program_name = "mke2fs"; -const char * device_name = NULL; +const char * device_name /* = NULL */; /* Command line options */ -int cflag = 0; -int verbose = 0; -int quiet = 0; -int super_only = 0; -int force = 0; -char *bad_blocks_filename = 0; -__u32 fs_stride = 0; +int cflag; +int verbose; +int quiet; +int super_only; +int force; +int noaction; +int journal_size; +int journal_flags; +char *bad_blocks_filename; +__u32 fs_stride; struct ext2_super_block param; -char *creator_os = NULL; -char *volume_label = NULL; -char *mount_dir = NULL; +char *creator_os; +char *volume_label; +char *mount_dir; +char *journal_device; +int sync_kludge; /* Set using the MKE2FS_SYNC env. option */ -static void usage(NOARGS), check_plausibility(NOARGS), check_mount(NOARGS); +int sys_page_size = 4096; -static void usage(NOARGS) +static void usage(void) { - fprintf(stderr, "Usage: %s [-c|-t|-l filename] [-b block-size] " - "[-f fragment-size]\n\t[-i bytes-per-inode] " + fprintf(stderr, _("Usage: %s [-c|-t|-l filename] [-b block-size] " + "[-f fragment-size]\n\t[-i bytes-per-inode] [-j] [-J journal-options]" " [-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] [-r fs-revision]\n\t[-R raid_opts]" - "[-s sparse-super-flag] [-qvSV] device [blocks-count]\n", + "[-M last-mounted-directory] [-O feature[,...]]\n\t" + "[-r fs-revision] [-R raid_opts] [-qvSV] device [blocks-count]\n"), program_name); exit(1); } -static int log2(int arg) +static int int_log2(int arg) { int l = 0; @@ -108,7 +110,7 @@ static int log2(int arg) return l; } -static int log10(unsigned int arg) +static int int_log10(unsigned int arg) { int l; @@ -117,68 +119,64 @@ static int log10(unsigned int arg) return l; } -static void proceed_question(NOARGS) -{ - fflush(stdout); - fflush(stderr); - printf("Proceed anyway? (y,n) "); - if (getchar() != 'y') - exit(1); -} - -#ifndef SCSI_BLK_MAJOR -#define SCSI_BLK_MAJOR(M) ((M) == SCSI_DISK_MAJOR || (M) == SCSI_CDROM_MAJOR) -#endif - -static void check_plausibility(NOARGS) -{ -#ifdef HAVE_LINUX_MAJOR_H - int val; - struct stat s; - - val = stat(device_name, &s); - - if(val == -1) { - fprintf(stderr, "Could not stat %s --- %s\n", - device_name, error_message(errno)); - if (errno == ENOENT) - fprintf(stderr, "\nThe device apparently does " - "not exist; did you specify it correctly?\n"); - exit(1); - } - if(!S_ISBLK(s.st_mode)) { - printf("%s is not a block special device.\n", device_name); - proceed_question(); - return; - } else if ((MAJOR(s.st_rdev) == HD_MAJOR && - MINOR(s.st_rdev)%64 == 0) || - (SCSI_BLK_MAJOR(MAJOR(s.st_rdev)) && - MINOR(s.st_rdev)%16 == 0)) { - printf("%s is entire device, not just one partition!\n", - device_name); - proceed_question(); - } -#endif -} - -static void check_mount(NOARGS) +/* + * This function sets the default parameters for a filesystem + * + * The type is specified by the user. The size is the maximum size + * (in megabytes) for which a set of parameters applies, with a size + * 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; + int size; + int blocksize; + int inode_ratio; +} settings[] = { + { default_str, 0, 4096, 8192 }, + { default_str, 512, 1024, 4096 }, + { default_str, 3, 1024, 8192 }, + { "journal", 0, 4096, 8192 }, + { "news", 0, 4096, 4096 }, + { "largefile", 0, DEF_MAX_BLOCKSIZE, 1024 * 1024 }, + { "largefile4", 0, DEF_MAX_BLOCKSIZE, 4096 * 1024 }, + { 0, 0, 0, 0}, +}; + +static void set_fs_defaults(const char *fs_type, + struct ext2_super_block *super, + int blocksize, int *inode_ratio) { - errcode_t retval; - int mount_flags; - - retval = ext2fs_check_if_mounted(device_name, &mount_flags); - if (retval) { - com_err("ext2fs_check_if_mount", retval, - "while determining whether %s is mounted.", - device_name); - return; + int megs; + int ratio = 0; + struct mke2fs_defaults *p; + + megs = super->s_blocks_count * (EXT2_BLOCK_SIZE(super) / 1024) / 1024; + if (inode_ratio) + ratio = *inode_ratio; + if (!fs_type) + fs_type = default_str; + for (p = settings; p->type; p++) { + if ((strcmp(p->type, fs_type) != 0) && + (strcmp(p->type, default_str) != 0)) + continue; + if ((p->size != 0) && + (megs > p->size)) + continue; + if (ratio == 0) + *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); + } } - if (!(mount_flags & EXT2_MF_MOUNTED)) - return; - - fprintf(stderr, "%s is mounted; will not make a filesystem here!\n", - device_name); - exit(1); + if (blocksize == 0) + super->s_blocks_count /= EXT2_BLOCK_SIZE(super) / 1024; } /* @@ -186,7 +184,7 @@ static void check_mount(NOARGS) */ 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; } @@ -202,14 +200,14 @@ static void read_bb_file(ext2_filsys fs, badblocks_list *bb_list, f = fopen(bad_blocks_file, "r"); if (!f) { com_err("read_bad_blocks_file", errno, - "while trying to open %s", bad_blocks_file); + _("while trying to open %s"), bad_blocks_file); exit(1); } retval = ext2fs_read_bb_FILE(fs, f, bb_list, invalid_block); fclose (f); if (retval) { com_err("ext2fs_read_bb_FILE", retval, - "while reading in list of bad blocks from file"); + _("while reading in list of bad blocks from file")); exit(1); } } @@ -223,22 +221,22 @@ static void test_disk(ext2_filsys fs, badblocks_list *bb_list) 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); + printf(_("Running command: %s\n"), buf); f = popen(buf, "r"); if (!f) { com_err("popen", errno, - "while trying run '%s'", buf); + _("while trying run '%s'"), buf); exit(1); } retval = ext2fs_read_bb_FILE(fs, f, bb_list, invalid_block); pclose(f); if (retval) { com_err("ext2fs_read_bb_FILE", retval, - "while processing list of bad blocks from program"); + _("while processing list of bad blocks from program")); exit(1); } } @@ -263,13 +261,13 @@ static void handle_bad_blocks(ext2_filsys fs, badblocks_list bb_list) */ 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)) { - fprintf(stderr, "Block %d in primary superblock/group " - "descriptor area bad.\n", i); - fprintf(stderr, "Blocks %d through %d must be good " - "in order to build a filesystem.\n", + 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 " + "in order to build a filesystem.\n"), fs->super->s_first_data_block, must_be_good); - fprintf(stderr, "Aborting....\n"); + fprintf(stderr, _("Aborting....\n")); exit(1); } } @@ -285,12 +283,12 @@ static void handle_bad_blocks(ext2_filsys fs, badblocks_list bb_list) 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" -" bad blocks.\n\n", +_("Warning: the backup superblock/group descriptors at block %d contain\n" +" bad blocks.\n\n"), group_block); group_bad++; group = ext2fs_group_of_blk(fs, group_block+j); @@ -304,70 +302,153 @@ static void handle_bad_blocks(ext2_filsys fs, badblocks_list bb_list) /* * 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, - "while marking bad blocks as used"); + 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 write_inode_tables(ext2_filsys fs) +/* + * These functions implement a generalized progress meter. + */ +struct progress_struct { + char format[20]; + char backup[80]; + __u32 max; +}; + +static void progress_init(struct progress_struct *progress, + const char *label,__u32 max) { - errcode_t retval; - blk_t blk; - int i, j, num, count; - char *buf; - char format[20], backup[80]; - int sync_kludge = 0; - char *mke2fs_sync; + int i; - mke2fs_sync = getenv("MKE2FS_SYNC"); - if (mke2fs_sync) - sync_kludge = atoi(mke2fs_sync); - - buf = malloc(fs->blocksize * STRIDE_LENGTH); - if (!buf) { - com_err("malloc", ENOMEM, "while allocating zeroizing buffer"); - exit(1); - } - memset(buf, 0, fs->blocksize * STRIDE_LENGTH); + memset(progress, 0, sizeof(struct progress_struct)); + if (quiet) + return; /* * Figure out how many digits we need */ - i = log10(fs->group_desc_count); - sprintf(format, "%%%dd/%%%dld", i, i); - memset(backup, '\b', sizeof(backup)-1); - backup[sizeof(backup)-1] = 0; - if ((2*i)+1 < sizeof(backup)) - backup[(2*i)+1] = 0; + i = int_log10(max); + sprintf(progress->format, "%%%dd/%%%dld", i, i); + memset(progress->backup, '\b', sizeof(progress->backup)-1); + progress->backup[sizeof(progress->backup)-1] = 0; + if ((2*i)+1 < sizeof(progress->backup)) + progress->backup[(2*i)+1] = 0; + progress->max = max; + + fputs(label, stdout); + fflush(stdout); +} + +static void progress_update(struct progress_struct *progress, __u32 val) +{ + if (progress->format[0] == 0) + return; + printf(progress->format, val, progress->max); + fputs(progress->backup, stdout); +} + +static void progress_close(struct progress_struct *progress) +{ + if (progress->format[0] == 0) + return; + fputs(_("done \n"), stdout); +} + + +/* + * Helper function which zeros out _num_ blocks starting at _blk_. In + * case of an error, the details of the error is returned via _ret_blk_ + * and _ret_count_ if they are non-NULL pointers. Returns 0 on + * success, and an error code on an error. + * + * As a special case, if the first argument is NULL, then it will + * attempt to free the static zeroizing buffer. (This is to keep + * programs that check for memory leaks happy.) + */ +static errcode_t zero_blocks(ext2_filsys fs, blk_t blk, int num, + struct progress_struct *progress, + blk_t *ret_blk, int *ret_count) +{ + int j, count, next_update, next_update_incr; + static char *buf; + errcode_t retval; + + /* If fs is null, clean up the static buffer and return */ + if (!fs) { + if (buf) { + free(buf); + buf = 0; + } + return 0; + } + /* Allocate the zeroizing buffer if necessary */ + if (!buf) { + buf = malloc(fs->blocksize * STRIDE_LENGTH); + if (!buf) { + com_err("malloc", ENOMEM, + _("while allocating zeroizing buffer")); + exit(1); + } + memset(buf, 0, fs->blocksize * STRIDE_LENGTH); + } + /* OK, do the write loop */ + next_update = 0; + next_update_incr = num / 100; + if (next_update_incr < 1) + next_update_incr = 1; + for (j=0; j < num; j += STRIDE_LENGTH, blk += STRIDE_LENGTH) { + count = num - j; + if (count > STRIDE_LENGTH) + count = STRIDE_LENGTH; + retval = io_channel_write_blk(fs->io, blk, count, buf); + if (retval) { + if (ret_count) + *ret_count = count; + if (ret_blk) + *ret_blk = blk; + return retval; + } + if (progress && j > next_update) { + next_update += num / 100; + progress_update(progress, blk); + } + } + return 0; +} + +static void write_inode_tables(ext2_filsys fs) +{ + errcode_t retval; + blk_t blk; + int i, num; + struct progress_struct progress; + + if (quiet) + memset(&progress, 0, sizeof(progress)); + else + progress_init(&progress, _("Writing inode tables: "), + fs->group_desc_count); - if (!quiet) - printf("Writing inode tables: "); for (i = 0; i < fs->group_desc_count; i++) { - if (!quiet) - printf(format, i, fs->group_desc_count); + progress_update(&progress, i); blk = fs->group_desc[i].bg_inode_table; num = fs->inode_blocks_per_group; - - for (j=0; j < num; j += STRIDE_LENGTH, blk += STRIDE_LENGTH) { - if (num-j > STRIDE_LENGTH) - count = STRIDE_LENGTH; - else - count = num - j; - retval = io_channel_write_blk(fs->io, blk, count, buf); - if (retval) - printf("Warning: could not write %d blocks " - "in inode table starting at %d: %s\n", - count, blk, error_message(retval)); + + retval = zero_blocks(fs, blk, num, 0, &blk, &num); + if (retval) { + fprintf(stderr, _("\nCould not write %d blocks " + "in inode table starting at %d: %s\n"), + num, blk, error_message(retval)); + exit(1); } - if (!quiet) - fputs(backup, stdout); if (sync_kludge) { if (sync_kludge == 1) sync(); @@ -375,9 +456,8 @@ static void write_inode_tables(ext2_filsys fs) sync(); } } - free(buf); - if (!quiet) - fputs("done \n", stdout); + zero_blocks(0, 0, 0, 0, 0, 0); + progress_close(&progress); } static void create_root_dir(ext2_filsys fs) @@ -387,14 +467,14 @@ static void create_root_dir(ext2_filsys fs) retval = ext2fs_mkdir(fs, EXT2_ROOT_INO, EXT2_ROOT_INO, 0); if (retval) { - com_err("ext2fs_mkdir", retval, "while creating root dir"); + com_err("ext2fs_mkdir", retval, _("while creating root dir")); exit(1); } if (geteuid()) { retval = ext2fs_read_inode(fs, EXT2_ROOT_INO, &inode); if (retval) { com_err("ext2fs_read_inode", retval, - "while reading root inode"); + _("while reading root inode")); exit(1); } inode.i_uid = getuid(); @@ -403,7 +483,7 @@ static void create_root_dir(ext2_filsys fs) retval = ext2fs_write_inode(fs, EXT2_ROOT_INO, &inode); if (retval) { com_err("ext2fs_write_inode", retval, - "while setting root inode ownership"); + _("while setting root inode ownership")); exit(1); } } @@ -412,30 +492,36 @@ static void create_root_dir(ext2_filsys fs) static void create_lost_and_found(ext2_filsys fs) { errcode_t retval; - ino_t ino; + ext2_ino_t ino; const char *name = "lost+found"; 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 creating /lost+found"); + com_err("ext2fs_mkdir", retval, + _("while creating /lost+found")); exit(1); } retval = ext2fs_lookup(fs, EXT2_ROOT_INO, name, strlen(name), 0, &ino); if (retval) { - com_err("ext2_lookup", retval, "while looking up /lost+found"); + com_err("ext2_lookup", retval, + _("while looking up /lost+found")); exit(1); } for (i=1; i < EXT2_NDIR_BLOCKS; i++) { + if ((lpf_size += fs->blocksize) >= 16*1024) + break; retval = ext2fs_expand_dir(fs, ino); if (retval) { com_err("ext2fs_expand_dir", retval, - "while expanding /lost+found"); + _("while expanding /lost+found")); exit(1); } - } + } } static void create_bad_block_inode(ext2_filsys fs, badblocks_list bb_list) @@ -448,7 +534,7 @@ static void create_bad_block_inode(ext2_filsys fs, badblocks_list bb_list) retval = ext2fs_update_bb_inode(fs, bb_list); if (retval) { com_err("ext2fs_update_bb_inode", retval, - "while setting bad block inode"); + _("while setting bad block inode")); exit(1); } @@ -456,8 +542,8 @@ static void create_bad_block_inode(ext2_filsys fs, badblocks_list bb_list) static void reserve_inodes(ext2_filsys fs) { - ino_t i; - int group; + ext2_ino_t i; + int group; for (i = EXT2_ROOT_INO + 1; i < EXT2_FIRST_INODE(fs->super); i++) { ext2fs_mark_inode_bitmap(fs->inode_map, i); @@ -468,100 +554,155 @@ static void reserve_inodes(ext2_filsys fs) ext2fs_mark_ib_dirty(fs); } -#ifdef ZAP_BOOTBLOCK -static void zap_bootblock(ext2_filsys fs) +#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; - memset(buf, 0, 512); - - retval = io_channel_write_blk(fs->io, 0, -512, buf); + buf = malloc(512*nsect); + if (!buf) { + printf(_("Out of memory erasing sectors %d-%d\n"), + sect, sect + nsect - 1); + exit(1); + } + + 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*nsect); + io_channel_set_blksize(fs->io, 512); + 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 block 0: %s\n", - 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) +{ + struct progress_struct progress; + errcode_t retval; + char *buf; + 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_init(&progress, _("Zeroing journal device: "), + fs->super->s_blocks_count); + + retval = zero_blocks(fs, 0, fs->super->s_blocks_count, + &progress, &blk, &count); + if (retval) { + com_err("create_journal_dev", retval, + _("while zeroing journal device (block %u, count %d)"), + blk, count); + exit(1); + } + zero_blocks(0, 0, 0, 0, 0, 0); + + retval = io_channel_write_blk(fs->io, + fs->super->s_first_data_block+1, + 1, buf); + if (retval) { + com_err("create_journal_dev", retval, + _("while writing journal superblock")); + exit(1); + } + progress_close(&progress); } -#endif - static void show_stats(ext2_filsys fs) { - struct ext2fs_sb *s = (struct ext2fs_sb *) fs->super; + struct ext2_super_block *s = fs->super; char buf[80]; blk_t group_block; 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)); + strncpy(buf, s->s_volume_name, sizeof(s->s_volume_name)); + printf(_("Filesystem label=%s\n"), buf); + printf(_("OS type: ")); switch (fs->super->s_creator_os) { case EXT2_OS_LINUX: printf ("Linux"); break; - case EXT2_OS_HURD: printf ("GNU/hurd"); break; + case EXT2_OS_HURD: printf ("GNU/Hurd"); break; case EXT2_OS_MASIX: printf ("Masix"); break; - default: printf ("(unknown os)"); + default: printf (_("(unknown os)")); } - printf (" ext2 filesystem format\n"); - memset(buf, 0, sizeof(buf)); - strncpy(buf, s->s_volume_name, sizeof(s->s_volume_name)); - printf("Filesystem label=%s\n", buf); - printf("%u inodes, %u blocks\n", s->s_inodes_count, + printf("\n"); + printf(_("Block size=%u (log=%u)\n"), fs->blocksize, + s->s_log_block_size); + printf(_("Fragment size=%u (log=%u)\n"), fs->fragsize, + s->s_log_frag_size); + printf(_("%u inodes, %u blocks\n"), s->s_inodes_count, s->s_blocks_count); - printf("%u blocks (%2.2f%%) reserved for the super user\n", + printf(_("%u blocks (%2.2f%%) reserved for the super user\n"), s->s_r_blocks_count, 100.0 * s->s_r_blocks_count / s->s_blocks_count); - printf("First data block=%u\n", s->s_first_data_block); - printf("Block size=%u (log=%u)\n", fs->blocksize, - s->s_log_block_size); - printf("Fragment size=%u (log=%u)\n", fs->fragsize, - s->s_log_frag_size); - printf("%lu block group%s\n", fs->group_desc_count, - (fs->group_desc_count > 1) ? "s" : ""); - printf("%u blocks per group, %u fragments per group\n", + printf(_("First data block=%u\n"), s->s_first_data_block); + if (fs->group_desc_count > 1) + printf(_("%u block groups\n"), fs->group_desc_count); + else + printf(_("%u block group\n"), fs->group_desc_count); + printf(_("%u blocks per group, %u fragments per group\n"), s->s_blocks_per_group, s->s_frags_per_group); - printf("%u inodes per group\n", s->s_inodes_per_group); + printf(_("%u inodes per group\n"), s->s_inodes_per_group); if (fs->group_desc_count == 1) { printf("\n"); return; } - printf("Superblock backups stored on blocks: "); + printf(_("Superblock backups stored on blocks: ")); group_block = s->s_first_data_block; col_left = 0; for (i = 1; i < fs->group_desc_count; i++) { group_block += s->s_blocks_per_group; if (!ext2fs_bg_has_super(fs, i)) continue; - need = log10(group_block) + 2; + if (i != 1) + printf(", "); + need = int_log10(group_block) + 2; if (need > col_left) { printf("\n\t"); col_left = 72; } col_left -= need; printf("%u", group_block); - if (i != fs->group_desc_count - 1) - printf(", "); } printf("\n\n"); } -#ifndef HAVE_STRCASECMP -static int strcasecmp (char *s1, char *s2) -{ - while (*s1 && *s2) { - int ch1 = *s1++, ch2 = *s2++; - if (isupper (ch1)) - ch1 = tolower (ch1); - if (isupper (ch2)) - ch2 = tolower (ch2); - if (ch1 != ch2) - return ch1 - ch2; - } - return *s1 ? 1 : *s2 ? -1 : 0; -} -#endif - /* * Set the S_CREATOR_OS field. Return true if OS is known, * otherwise, 0. @@ -592,8 +733,8 @@ static void parse_raid_opts(const char *opts) len = strlen(opts); buf = malloc(len+1); if (!buf) { - fprintf(stderr, "Couldn't allocate memory to parse " - "raid options!\n"); + fprintf(stderr, _("Couldn't allocate memory to parse " + "raid options!\n")); exit(1); } strcpy(buf, opts); @@ -616,7 +757,8 @@ static void parse_raid_opts(const char *opts) } fs_stride = strtoul(arg, &p, 0); if (*p || (fs_stride == 0)) { - fprintf(stderr, "Invalid stride parameter.\n"); + fprintf(stderr, + _("Invalid stride parameter.\n")); raid_usage++; continue; } @@ -624,34 +766,46 @@ static void parse_raid_opts(const char *opts) raid_usage++; } if (raid_usage) { - fprintf(stderr, "\nBad raid options specified.\n\n" + fprintf(stderr, _("\nBad raid options specified.\n\n" "Raid options are separated by commas, " "and may take an argument which\n" "\tis set off by an equals ('=') sign.\n\n" "Valid raid options are:\n" - "\tstride=\n\n"); + "\tstride=\n\n")); exit(1); } } +static __u32 ok_features[3] = { + EXT3_FEATURE_COMPAT_HAS_JOURNAL, /* Compat */ + EXT2_FEATURE_INCOMPAT_FILETYPE| /* Incompat */ + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV, + EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER /* R/O compat */ +}; static void PRS(int argc, char *argv[]) { - int c; - int size; - char * tmp; - blk_t max = 8192; - int inode_ratio = 4096; - int reserved_ratio = 5; - ino_t num_inodes = 0; + int c; + int size; + char * tmp; + 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"); - struct ext2fs_sb *param_ext2 = (struct ext2fs_sb *) ¶m; - char *raid_opts = 0; - blk_t dev_size; - + char * oldpath = getenv("PATH"); + char * raid_opts = 0; + const char * fs_type = 0; + int default_features = 1; + blk_t dev_size; +#ifdef __linux__ + struct utsname ut; +#endif + long sysval; + /* Update our PATH to include /sbin */ if (oldpath) { char *newpath; @@ -664,73 +818,131 @@ static void PRS(int argc, char *argv[]) } else putenv (PATH_SET); + 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)); - - 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_rev_level = 1; /* Create revision 1 filesystems now */ + 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:l:m:o:qr:R:s:tvI:SFL:M:N:V")) != EOF) + "b:cf:g:i:jl:m:no:qr:R:s:tvI:J:ST:FL:M:N:O:V")) != EOF) switch (c) { case 'b': - size = strtoul(optarg, &tmp, 0); - if (size < 1024 || size > 4096 || *tmp) { - com_err(program_name, 0, "bad block size - %s", - optarg); + blocksize = strtoul(optarg, &tmp, 0); + 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 = - log2(size >> EXT2_MIN_BLOCK_LOG_SIZE); - max = size * 8; + 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) { - com_err(program_name, 0, "bad fragment size - %s", + if (size < EXT2_MIN_BLOCK_SIZE || + size > EXT2_MAX_BLOCK_SIZE || *tmp) { + com_err(program_name, 0, + _("bad fragment size - %s"), optarg); exit(1); } param.s_log_frag_size = - log2(size >> EXT2_MIN_BLOCK_LOG_SIZE); - printf("Warning: fragments not supported. " - "Ignoring -f option\n"); + int_log2(size >> EXT2_MIN_BLOCK_LOG_SIZE); + fprintf(stderr, _("Warning: fragments not supported. " + "Ignoring -f option\n")); break; case 'g': param.s_blocks_per_group = strtoul(optarg, &tmp, 0); if (*tmp) { com_err(program_name, 0, - "Illegal number for blocks per group"); + _("Illegal number for blocks per group")); exit(1); } if ((param.s_blocks_per_group % 8) != 0) { com_err(program_name, 0, - "blocks per group must be multiple of 8"); + _("blocks per group must be multiple of 8")); exit(1); } break; case 'i': inode_ratio = strtoul(optarg, &tmp, 0); - if (inode_ratio < 1024 || inode_ratio > 256 * 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); + com_err(program_name, 0, + _("bad inode ratio %s (min %d/max %d"), + optarg, EXT2_MIN_BLOCK_SIZE, + EXT2_MAX_BLOCK_SIZE); exit(1); } break; + case 'J': + parse_journal_opts(optarg); + break; + case 'j': + param.s_feature_compat |= + EXT3_FEATURE_COMPAT_HAS_JOURNAL; + if (!journal_size) + journal_size = -1; + break; case 'l': bad_blocks_filename = malloc(strlen(optarg)+1); if (!bad_blocks_filename) { com_err(program_name, ENOMEM, - "in malloc for bad_blocks_filename"); + _("in malloc for bad_blocks_filename")); exit(1); } strcpy(bad_blocks_filename, optarg); @@ -739,23 +951,41 @@ static void PRS(int argc, char *argv[]) reserved_ratio = strtoul(optarg, &tmp, 0); if (reserved_ratio > 50 || *tmp) { com_err(program_name, 0, - "bad reserved blocks percent - %s", + _("bad reserved blocks percent - %s"), optarg); exit(1); } break; + case 'n': + noaction++; + break; case 'o': creator_os = optarg; 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': @@ -776,15 +1006,35 @@ static void PRS(int argc, char *argv[]) case 'M': mount_dir = optarg; break; + case 'O': + 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; break; case 'S': super_only = 1; break; + case 'T': + fs_type = optarg; + break; case 'V': /* Print version number and exit */ - fprintf(stderr, "\tUsing %s\n", + fprintf(stderr, _("\tUsing %s\n"), error_message(EXT2_ET_BASE)); exit(0); default: @@ -795,12 +1045,14 @@ static void PRS(int argc, char *argv[]) device_name = argv[optind]; optind++; if (optind < argc) { - param.s_blocks_count = strtoul(argv[optind++], &tmp, 0); - if (*tmp) { - com_err(program_name, 0, "bad blocks count - %s", + unsigned long tmp2 = strtoul(argv[optind++], &tmp, 0); + + if ((*tmp) || (tmp2 > 0xfffffffful)) { + com_err(program_name, 0, _("bad blocks count - %s"), argv[optind - 1]); exit(1); } + param.s_blocks_count = tmp2; } if (optind < argc) usage(); @@ -808,49 +1060,141 @@ static void PRS(int argc, char *argv[]) if (raid_opts) parse_raid_opts(raid_opts); + /* + * 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(); - check_mount(); + check_plausibility(device_name); + check_mount(device_name, force, _("filesystem")); param.s_log_frag_size = param.s_log_block_size; - retval = ext2fs_get_device_size(device_name, - EXT2_BLOCK_SIZE(¶m), - &dev_size); + if (noaction && param.s_blocks_count) { + dev_size = param.s_blocks_count; + retval = 0; + } else + retval = ext2fs_get_device_size(device_name, + EXT2_BLOCK_SIZE(¶m), + &dev_size); if (retval && (retval != EXT2_ET_UNIMPLEMENTED)) { com_err(program_name, retval, - "while trying to determine filesystem size"); + _("while trying to determine filesystem size")); exit(1); } if (!param.s_blocks_count) { if (retval == EXT2_ET_UNIMPLEMENTED) { com_err(program_name, 0, - "Couldn't determine device size; you " + _("Couldn't determine device size; you " "must specify\nthe size of the " - "filesystem\n"); + "filesystem\n")); exit(1); - } else + } else { + if (dev_size == 0) { + com_err(program_name, 0, + _("Device size reported to be zero. " + "Invalid partition specified, or\n\t" + "partition table wasn't reread " + "after running fdisk, due to\n\t" + "a modified partition being busy " + "and in use. You may need to reboot\n\t" + "to re-read your partition table.\n" + )); + exit(1); + } param.s_blocks_count = dev_size; + } + } else if (!force && (param.s_blocks_count > dev_size)) { com_err(program_name, 0, - "Filesystem larger than apparent filesystem size."); + _("Filesystem larger than apparent filesystem size.")); proceed_question(); } + /* + * If the user asked for HAS_JOURNAL, then make sure a journal + * gets created. + */ + if ((param.s_feature_compat & EXT3_FEATURE_COMPAT_HAS_JOURNAL) && + !journal_size) + journal_size = -1; + + set_fs_defaults(fs_type, ¶m, blocksize, &inode_ratio); + if (param.s_blocks_per_group) { if (param.s_blocks_per_group < 256 || - param.s_blocks_per_group > max || *tmp) { + param.s_blocks_per_group > group_blk_max || *tmp) { com_err(program_name, 0, - "blocks per group count out of range"); + _("blocks per group count out of range")); exit(1); } } + 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_inodes_count = num_inodes ? num_inodes : - ((long long) param.s_blocks_count * EXT2_BLOCK_SIZE(¶m)) + ((__u64) param.s_blocks_count * EXT2_BLOCK_SIZE(¶m)) / inode_ratio; /* @@ -858,19 +1202,6 @@ static void PRS(int argc, char *argv[]) */ param.s_r_blocks_count = (param.s_blocks_count * reserved_ratio) / 100; - /* - * If we are using revision #1, use the sparse super feature - * by default - */ -#ifdef EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER - if ((sparse_option == 1) -#ifdef EXT2_DYNAMIC_REV - || ((param.s_rev_level >= EXT2_DYNAMIC_REV) && (!sparse_option)) -#endif - ) - param_ext2->s_feature_ro_compat |= - EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; -#endif } int main (int argc, char *argv[]) @@ -878,8 +1209,15 @@ int main (int argc, char *argv[]) errcode_t retval = 0; ext2_filsys fs; badblocks_list bb_list = 0; - struct ext2fs_sb *s; - + int journal_blocks; + int i, val; + +#ifdef ENABLE_NLS + setlocale(LC_MESSAGES, ""); + setlocale(LC_CTYPE, ""); + bindtextdomain(NLS_CAT_NAME, LOCALEDIR); + textdomain(NLS_CAT_NAME); +#endif PRS(argc, argv); /* @@ -888,45 +1226,78 @@ int main (int argc, char *argv[]) retval = ext2fs_initialize(device_name, 0, ¶m, unix_io_manager, &fs); if (retval) { - com_err(device_name, retval, "while setting up superblock"); + com_err(device_name, retval, _("while setting up superblock")); exit(1); } /* + * Wipe out the old on-disk superblock + */ + if (!noaction) + zap_sector(fs, 2, 6); + + /* * Generate a UUID for it... */ - s = (struct ext2fs_sb *) fs->super; - uuid_generate(s->s_uuid); + uuid_generate(fs->super->s_uuid); + + /* + * Add "jitter" to the superblock's check interval so that we + * don't check all the filesystems at the same time. We use a + * kludgy hack of using the UUID to derive a random jitter value. + */ + for (i = 0, val = 0 ; i < sizeof(fs->super->s_uuid); i++) + val += fs->super->s_uuid[i]; + fs->super->s_max_mnt_count += val % EXT2_DFL_MAX_MNT_COUNT; /* * Override the creator OS, if applicable */ if (creator_os && !set_os(fs->super, creator_os)) { - com_err (program_name, 0, "unknown os - %s", creator_os); + com_err (program_name, 0, _("unknown os - %s"), creator_os); exit(1); } /* + * For the Hurd, we will turn off filetype since it doesn't + * support it. + */ + if (fs->super->s_creator_os == EXT2_OS_HURD) + fs->super->s_feature_incompat &= + ~EXT2_FEATURE_INCOMPAT_FILETYPE; + + /* * Set the volume label... */ if (volume_label) { - memset(s->s_volume_name, 0, sizeof(s->s_volume_name)); - strncpy(s->s_volume_name, volume_label, - sizeof(s->s_volume_name)); + memset(fs->super->s_volume_name, 0, + sizeof(fs->super->s_volume_name)); + strncpy(fs->super->s_volume_name, volume_label, + sizeof(fs->super->s_volume_name)); } /* * Set the last mount directory */ if (mount_dir) { - memset(s->s_last_mounted, 0, sizeof(s->s_last_mounted)); - strncpy(s->s_last_mounted, mount_dir, - sizeof(s->s_last_mounted)); + memset(fs->super->s_last_mounted, 0, + sizeof(fs->super->s_last_mounted)); + strncpy(fs->super->s_last_mounted, mount_dir, + sizeof(fs->super->s_last_mounted)); } - if (!quiet) + if (!quiet || noaction) show_stats(fs); + if (noaction) + exit(0); + + if (fs->super->s_feature_incompat & + EXT3_FEATURE_INCOMPAT_JOURNAL_DEV) { + create_journal_dev(fs); + exit(ext2fs_close(fs) ? 1 : 0); + } + if (bad_blocks_filename) read_bb_file(fs, &bb_list, bad_blocks_filename); if (cflag) @@ -937,28 +1308,116 @@ int main (int argc, char *argv[]) retval = ext2fs_allocate_tables(fs); if (retval) { com_err(program_name, retval, - "while trying to allocate filesystem tables"); + _("while trying to allocate filesystem tables")); exit(1); } if (super_only) { 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, + _("while zeroing block %u at end of filesystem"), + ret_blk); + } 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_bootblock(fs); -#endif } - - if (!quiet) - printf("Writing superblocks and " - "filesystem accounting information: "); - ext2fs_close(fs); + + if (journal_device) { + ext2_filsys jfs; + + if (!force) + check_plausibility(journal_device); + check_mount(journal_device, force, _("journal")); + + retval = ext2fs_open(journal_device, EXT2_FLAG_RW| + EXT2_FLAG_JOURNAL_DEV_OK, 0, + fs->blocksize, unix_io_manager, &jfs); + if (retval) { + com_err(program_name, retval, + _("while trying to open journal device %s\n"), + journal_device); + exit(1); + } + if (!quiet) { + printf(_("Adding journal to device %s: "), + journal_device); + fflush(stdout); + } + retval = ext2fs_add_journal_device(fs, jfs); + if(retval) { + com_err (program_name, retval, + _("\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); + + if (!journal_blocks) { + fs->super->s_feature_compat &= + ~EXT3_FEATURE_COMPAT_HAS_JOURNAL; + goto no_journal; + } + if (!quiet) { + printf(_("Creating journal (%d blocks): "), + journal_blocks); + fflush(stdout); + } + retval = ext2fs_add_journal_inode(fs, journal_blocks, + journal_flags); + if (retval) { + com_err (program_name, retval, + _("\n\twhile trying to create journal")); + exit(1); + } + if (!quiet) + printf(_("done\n")); + } +no_journal: + if (!quiet) - printf("done\n"); - return 0; + printf(_("Writing superblocks and " + "filesystem accounting information: ")); + retval = ext2fs_flush(fs); + if (retval) { + fprintf(stderr, + _("\nWarning, had trouble writing out superblocks.")); + } + if (!quiet) { + printf(_("done\n\n")); + print_check_message(fs); + } + val = ext2fs_close(fs); + return (retval || val) ? 1 : 0; }