From 63985320384bf143eaac9857af424800d9867a1a Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Wed, 3 Jan 2001 17:02:13 +0000 Subject: [PATCH] ChangeLog, Makefile.in, mke2fs.c, tune2fs.8.in, tune2fs.c, util.c, util.h: tune2fs.c (update_feature_set, add_journal): Moved to separate functions. Added ability to add and remove the journal while the filesystem is live. Added support for setting a time-based UUID. Removed zero-initialized static variables. mke2fs.c, util.c, util.h (strcasecmp, proceed_question, check_plausibility, parse_journal_opts, check_mount): Moved functions to util.c so they can be used by tune2fs. mke2fs.c (main): Change ext2fs_add_journal_fs() to ext2fs_add_journal_inode() to reflect function renaming. --- misc/ChangeLog | 14 +++ misc/Makefile.in | 17 ++-- misc/mke2fs.c | 190 ++------------------------------------- misc/tune2fs.8.in | 9 +- misc/tune2fs.c | 262 +++++++++++++++++++++++++++++++++++++----------------- misc/util.c | 198 +++++++++++++++++++++++++++++++++++++++++ misc/util.h | 23 +++++ 7 files changed, 437 insertions(+), 276 deletions(-) create mode 100644 misc/util.c create mode 100644 misc/util.h diff --git a/misc/ChangeLog b/misc/ChangeLog index 3a02bd3..2ba1819 100644 --- a/misc/ChangeLog +++ b/misc/ChangeLog @@ -1,3 +1,17 @@ +2001-01-03 + + * tune2fs.c (update_feature_set, add_journal): Moved to separate + functions. Added ability to add and remove the journal + while the filesystem is live. Added support for setting + a time-based UUID. Removed zero-initialized static variables. + + * mke2fs.c, util.c, util.h (strcasecmp, proceed_question, + check_plausibility, parse_journal_opts, check_mount): + Moved functions to util.c so they can be used by tune2fs. + + * mke2fs.c (main): Change ext2fs_add_journal_fs() to + ext2fs_add_journal_inode() to reflect function renaming. + 2001-01-01 * mke2fs.c, e2image.c: Removed references to struct ext2fs_sb to diff --git a/misc/Makefile.in b/misc/Makefile.in index b75d81c..10832dc 100644 --- a/misc/Makefile.in +++ b/misc/Makefile.in @@ -19,9 +19,9 @@ SMANPAGES= tune2fs.8 mklost+found.8 mke2fs.8 dumpe2fs.8 badblocks.8 \ UPROGS= chattr lsattr uuidgen UMANPAGES= chattr.1 lsattr.1 uuidgen.1 -TUNE2FS_OBJS= tune2fs.o +TUNE2FS_OBJS= tune2fs.o util.o MKLPF_OBJS= mklost+found.o -MKE2FS_OBJS= mke2fs.o +MKE2FS_OBJS= mke2fs.o util.o CHATTR_OBJS= chattr.o LSATTR_OBJS= lsattr.o UUIDGEN_OBJS= uuidgen.o @@ -33,7 +33,8 @@ FSCK_OBJS= fsck.o get_device_by_label.o base_device.o SRCS= $(srcdir)/tune2fs.c $(srcdir)/mklost+found.c $(srcdir)/mke2fs.c \ $(srcdir)/chattr.c $(srcdir)/lsattr.c $(srcdir)/dumpe2fs.c \ - $(srcdir)/badblocks.c $(srcdir)/fsck.c $(srcdir)/uuidgen.c + $(srcdir)/badblocks.c $(srcdir)/fsck.c $(srcdir)/util.c \ + $(srcdir)/uuidgen.c LIBS= $(LIBEXT2FS) $(LIBCOM_ERR) DEPLIBS= $(LIBEXT2FS) $(LIBCOM_ERR) @@ -192,7 +193,8 @@ tune2fs.o: $(srcdir)/tune2fs.c $(top_srcdir)/include/linux/ext2_fs.h \ $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/et/com_err.h \ $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ $(top_srcdir)/lib/ext2fs/bitops.h $(top_srcdir)/lib/uuid/uuid.h \ - $(top_srcdir)/lib/e2p/e2p.h $(top_srcdir)/version.h $(srcdir)/nls-enable.h + $(top_srcdir)/lib/e2p/e2p.h $(srcdir)/util.h $(top_srcdir)/version.h \ + $(srcdir)/nls-enable.h mklost+found.o: $(srcdir)/mklost+found.c \ $(top_srcdir)/include/linux/ext2_fs.h $(top_srcdir)/version.h \ $(srcdir)/nls-enable.h @@ -200,7 +202,7 @@ mke2fs.o: $(srcdir)/mke2fs.c $(top_srcdir)/include/linux/ext2_fs.h \ $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/uuid/uuid.h \ $(top_srcdir)/lib/e2p/e2p.h $(top_srcdir)/lib/ext2fs/ext2fs.h \ $(top_srcdir)/lib/ext2fs/ext2_io.h $(top_builddir)/lib/ext2fs/ext2_err.h \ - $(top_srcdir)/lib/ext2fs/bitops.h $(top_srcdir)/version.h \ + $(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/util.h $(top_srcdir)/version.h \ $(srcdir)/nls-enable.h chattr.o: $(srcdir)/chattr.c $(top_srcdir)/include/linux/ext2_fs.h \ $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/e2p/e2p.h \ @@ -219,5 +221,10 @@ badblocks.o: $(srcdir)/badblocks.c $(top_srcdir)/lib/et/com_err.h \ $(top_srcdir)/lib/ext2fs/bitops.h $(srcdir)/nls-enable.h fsck.o: $(srcdir)/fsck.c $(top_srcdir)/version.h $(srcdir)/nls-enable.h \ $(srcdir)/fsck.h $(srcdir)/get_device_by_label.h +util.o: $(srcdir)/util.c $(top_srcdir)/include/linux/ext2_fs.h \ + $(top_srcdir)/lib/et/com_err.h $(top_srcdir)/lib/e2p/e2p.h \ + $(top_srcdir)/lib/ext2fs/ext2fs.h $(top_srcdir)/lib/ext2fs/ext2_io.h \ + $(top_builddir)/lib/ext2fs/ext2_err.h $(top_srcdir)/lib/ext2fs/bitops.h \ + $(srcdir)/nls-enable.h $(srcdir)/util.h uuidgen.o: $(srcdir)/uuidgen.c $(top_srcdir)/lib/uuid/uuid.h \ $(srcdir)/nls-enable.h diff --git a/misc/mke2fs.c b/misc/mke2fs.c index a6161d6..9e90c53 100644 --- a/misc/mke2fs.c +++ b/misc/mke2fs.c @@ -45,21 +45,15 @@ extern int optind; #include #include -#ifdef HAVE_LINUX_MAJOR_H -#include -#include /* Only need sys/stat.h for major nr test */ -#endif #include "et/com_err.h" #include "uuid/uuid.h" #include "e2p/e2p.h" #include "ext2fs/ext2fs.h" +#include "util.h" #include "../version.h" #include "nls-enable.h" -/* Everything is STDC, these days */ -#define NOARGS void - #define STRIDE_LENGTH 8 #ifndef __sparc__ @@ -90,11 +84,7 @@ char *volume_label /* = NULL */ ; char *mount_dir /* = NULL */ ; char *journal_device /* = NULL */ ; -static void usage(NOARGS); -static void check_plausibility(const char *device); -static void check_mount(const char *device); - -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] [-j journal-options]" @@ -128,85 +118,6 @@ static int int_log10(unsigned int arg) return l; } -static void proceed_question(NOARGS) -{ - char buf[256]; - char *short_yes = _("yY"); - - fflush(stdout); - fflush(stderr); - printf(_("Proceed anyway? (y,n) ")); - buf[0] = 0; - fgets(buf, sizeof(buf), stdin); - if (strchr(short_yes, buf[0]) == 0) - exit(1); -} - -#ifndef SCSI_BLK_MAJOR -#define SCSI_BLK_MAJOR(M) ((M) == SCSI_DISK_MAJOR || (M) == SCSI_CDROM_MAJOR) -#endif - -static void check_plausibility(const char *device) -{ -#ifdef HAVE_LINUX_MAJOR_H -#ifndef MAJOR -#define MAJOR(dev) ((dev)>>8) -#define MINOR(dev) ((dev) & 0xff) -#endif - - int val; - struct stat s; - - val = stat(device, &s); - - if(val == -1) { - fprintf(stderr, _("Could not stat %s --- %s\n"), - device, 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); - 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); - proceed_question(); - } -#endif -} - -static void check_mount(const char *device) -{ - errcode_t retval; - int mount_flags; - - retval = ext2fs_check_if_mounted(device, &mount_flags); - if (retval) { - com_err("ext2fs_check_if_mount", retval, - _("while determining whether %s is mounted."), - device); - return; - } - if (!(mount_flags & EXT2_MF_MOUNTED)) - return; - - fprintf(stderr, _("%s is mounted; "), device); - if (force) { - fprintf(stderr, _("mke2fs forced anyway. " - "Hope /etc/mtab is incorrect.\n")); - } else { - fprintf(stderr, _("will not make a filesystem here!\n")); - exit(1); - } -} - /* * This function sets the default parameters for a filesystem * @@ -634,22 +545,6 @@ static void show_stats(ext2_filsys fs) 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. @@ -723,79 +618,6 @@ static void parse_raid_opts(const char *opts) } } -static void parse_journal_opts(const char *opts) -{ - char *buf, *token, *next, *p, *arg; - int len; - int journal_usage = 0; - - len = strlen(opts); - buf = malloc(len+1); - if (!buf) { - fprintf(stderr, _("Couldn't allocate memory to parse " - "journal options!\n")); - exit(1); - } - strcpy(buf, opts); - for (token = buf; token && *token; token = next) { - p = strchr(token, ','); - next = 0; - if (p) { - *p = 0; - next = p+1; - } - arg = strchr(token, '='); - if (arg) { - *arg = 0; - arg++; - } - printf("Journal option=%s, argument=%s\n", token, - arg ? arg : "NONE"); - if (strcmp(token, "device") == 0) { - if (!arg) { - journal_usage++; - continue; - } - journal_device = arg; - } else if (strcmp(token, "size") == 0) { - if (!arg) { - journal_usage++; - continue; - } - journal_size = strtoul(arg, &p, 0); - journal_size_check: - if (*p || (journal_size < 4 || journal_size > 100)) { - fprintf(stderr, - _("Invalid journal size parameter - %s.\n"), - arg); - journal_usage++; - continue; - } - } else if (strcmp(token, "v1_superblock") == 0) { - journal_flags |= EXT2_MKJOURNAL_V1_SUPER; - continue; - } else { - journal_size = strtoul(token, &p, 0); - if (*p) - journal_usage++; - else - goto journal_size_check; - } - } - if (journal_usage) { - fprintf(stderr, _("\nBad journal options specified.\n\n" - "Journal 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" - "\tsize=\n" - "\tdevice=\n\n" - "Journal size must be between " - "4 and 100 megabytes.\n\n" )); - exit(1); - } -} - static __u32 ok_features[3] = { 0, /* Compat */ EXT2_FEATURE_INCOMPAT_FILETYPE, /* Incompat */ @@ -1011,7 +833,7 @@ static void PRS(int argc, char *argv[]) if (!force) check_plausibility(device_name); - check_mount(device_name); + check_mount(device_name, force, _("filesystem")); param.s_log_frag_size = param.s_log_block_size; @@ -1206,7 +1028,7 @@ int main (int argc, char *argv[]) if (journal_device) { if (!force) check_plausibility(journal_device); - check_mount(journal_device); + check_mount(journal_device, force, _("journal")); if (!quiet) printf(_("Creating journal on device %s: "), @@ -1226,8 +1048,8 @@ int main (int argc, char *argv[]) if (!quiet) printf(_("Creating journal (%d blocks): "), journal_blocks); - retval = ext2fs_add_journal_fs(fs, journal_blocks, - journal_flags); + retval = ext2fs_add_journal_inode(fs, journal_blocks, + journal_flags); if (retval) { com_err (program_name, retval, _("while trying to create journal")); diff --git a/misc/tune2fs.8.in b/misc/tune2fs.8.in index f7f7ecf..fcf1057 100644 --- a/misc/tune2fs.8.in +++ b/misc/tune2fs.8.in @@ -154,11 +154,14 @@ e2fsck must be run on the filesystem. set the UUID of the filesystem. A sample UUID looks like this: "c1b9d5a2-f162-11cf-9ece-0020afc76f16". The uuid may also be .IR null , -which will set the filesystem UUID to the null UUID. The uuid may also be +which will set the filesystem UUID to the null UUID (clearing it), .IR random , -which will generate a new random UUID for the filesystem. +which will generate a new random-based UUID for the filesystem, or +.IR time , +which will generate a new time-based UUID for the filesystem (see +.BR uuidgen (8)). .SH BUGS -We haven't found any bugs yet. Perhaps there are bugs but it's unlikely. +We haven't found any bugs yet. That doesn't mean there aren't any... .SH WARNING Never use tune2fs to change parameters of a read/write mounted filesystem! .B Use this utility diff --git a/misc/tune2fs.c b/misc/tune2fs.c index 4a61a12..adbc1a9 100644 --- a/misc/tune2fs.c +++ b/misc/tune2fs.c @@ -48,59 +48,33 @@ extern int optind; #include "et/com_err.h" #include "uuid/uuid.h" #include "e2p/e2p.h" +#include "util.h" #include "../version.h" #include "nls-enable.h" const char * program_name = "tune2fs"; -char * device_name = NULL; -char * new_label = NULL; -char * new_last_mounted = NULL; -char * new_UUID = NULL; -int c_flag = 0; -int C_flag = 0; -int e_flag = 0; -int g_flag = 0; -int i_flag = 0; -int l_flag = 0; -int L_flag = 0; -int m_flag = 0; -int M_flag = 0; -int r_flag = 0; -int s_flag = -1; -int u_flag = 0; -int U_flag = 0; -int max_mount_count, mount_count; -unsigned long interval; -unsigned long reserved_ratio = 0; -unsigned long reserved_blocks = 0; -unsigned short errors; -unsigned long resgid = 0; -unsigned long resuid = 0; +char * device_name; +char * new_label, *new_last_mounted, *new_UUID, *journal_opts; +static int c_flag, C_flag, e_flag, g_flag, i_flag, l_flag, L_flag; +static int m_flag, M_flag, r_flag, s_flag = -1, u_flag, U_flag; +static int max_mount_count, mount_count, mount_flags; +static unsigned long interval, reserved_ratio, reserved_blocks; +static unsigned long resgid, resuid; +static unsigned short errors; -#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 +int journal_size, journal_flags; +char *journal_device; + +static const char *please_fsck = N_("Please run e2fsck on the filesystem.\n"); static void usage(void) { fprintf(stderr, _("Usage: %s [-c max-mounts-count] [-e errors-behavior] " "[-g group]\n" - "\t[-i interval[d|m|w]] [-l] [-s sparse-flag] " - "[-m reserved-blocks-percent]\n" + "\t[-i interval[d|m|w]] [-j journal-options]\n" + "\t[-l] [-s sparse-flag] [-m reserved-blocks-percent]\n" "\t[-r reserved-blocks-count] [-u user] [-C mount-count]\n" "\t[-L volume-label] [-M last-mounted-dir] [-U UUID]\n" "\t[-O [^]feature[,...]] device\n"), program_name); @@ -113,7 +87,155 @@ static __u32 ok_features[3] = { EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER /* R/O compat */ }; -static const char *please_fsck = N_("Please run e2fsck on the filesystem.\n"); +/* + * Update the feature set as provided by the user. + */ +static void update_feature_set(ext2_filsys fs, char *features_cmd) +{ + int sparse, old_sparse, filetype, old_filetype; + int journal, old_journal; + struct ext2_inode inode; + struct ext2_super_block *sb= fs->super; + errcode_t retval; + + old_sparse = sb->s_feature_ro_compat & + EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; + old_filetype = sb->s_feature_incompat & + EXT2_FEATURE_INCOMPAT_FILETYPE; + old_journal = sb->s_feature_compat & + EXT3_FEATURE_COMPAT_HAS_JOURNAL; + if (e2p_edit_feature(features_cmd, &sb->s_feature_compat, + ok_features)) { + fprintf(stderr, _("Invalid filesystem option set: %s\n"), + features_cmd); + exit(1); + } + sparse = sb->s_feature_ro_compat & + EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; + filetype = sb->s_feature_incompat & + EXT2_FEATURE_INCOMPAT_FILETYPE; + journal = sb->s_feature_compat & + EXT3_FEATURE_COMPAT_HAS_JOURNAL; + if (old_journal && !journal) { + if ((mount_flags & EXT2_MF_MOUNTED) && + !(mount_flags & EXT2_MF_READONLY)) { + fprintf(stderr, + _("The HAS_JOURNAL flag may only be " + "cleared when the filesystem is\n" + "unmounted or mounted " + "read-only.\n")); + exit(1); + } + if (sb->s_feature_incompat & + EXT3_FEATURE_INCOMPAT_RECOVER) { + fprintf(stderr, + _("The NEEDS_RECOVERY flag is set. " + "Please run e2fsck before clearing\n" + "the HAS_JOURNAL flag.\n")); + exit(1); + } + /* + * Remove the immutable flag on the journal inode + */ + if (sb->s_journal_inum) { + retval = ext2fs_read_inode(fs, sb->s_journal_inum, + &inode); + if (retval) { + com_err(program_name, retval, + "while reading journal inode"); + exit(1); + } + inode.i_flags &= ~EXT2_IMMUTABLE_FL; + retval = ext2fs_write_inode(fs, sb->s_journal_inum, + &inode); + if (retval) { + com_err(program_name, retval, + "while write journal inode"); + exit(1); + } + } + } + if (journal && !old_journal) { + /* + * If adding a journal flag, let the create journal + * code below handle creating setting the flag and + * creating the journal. We supply a default size if + * necessary. + */ + if (!journal_opts) + journal_opts = "size=16"; + sb->s_feature_compat &=~EXT3_FEATURE_COMPAT_HAS_JOURNAL; + journal = old_journal; + } + + if (sb->s_rev_level == EXT2_GOOD_OLD_REV && + (sb->s_feature_compat || sb->s_feature_ro_compat || + sb->s_feature_incompat)) + ext2fs_update_dynamic_rev(fs); + if ((sparse != old_sparse) || + (filetype != old_filetype) || + (journal != old_journal)) { + sb->s_state &= ~EXT2_VALID_FS; + printf("\n%s\n", _(please_fsck)); + } + ext2fs_mark_super_dirty(fs); +} + +/* + * Add a journal to the filesystem. + */ +static void add_journal(ext2_filsys fs) +{ + unsigned long journal_blocks; + errcode_t retval; + + if (fs->super->s_feature_compat & + EXT3_FEATURE_COMPAT_HAS_JOURNAL) { + fprintf(stderr, _("The filesystem already has a journal.\n")); + exit(1); + } + parse_journal_opts(journal_opts); + journal_blocks = journal_size * 1024 / (fs->blocksize / 1024); + if (journal_device) { + check_plausibility(journal_device); + check_mount(journal_device, 0, _("journal")); + printf(_("Creating journal on device %s: "), + journal_device); + retval = ext2fs_add_journal_device(fs, journal_device, + journal_blocks, + journal_flags); + if (retval) { + com_err (program_name, retval, + _("while trying to create journal on device %s"), + journal_device); + exit(1); + } + printf(_("done\n")); + } else if (journal_size) { + errcode_t retval; + int mount_flags; + + printf(_("Creating journal inode: ")); + fflush(stdout); + retval = ext2fs_add_journal_inode(fs, journal_blocks, + journal_flags); + if (retval) { + printf("\n"); + com_err(program_name, retval, + _("while trying to create journal")); + exit(1); + } + printf(_("done\n")); + /* + * If the filesystem wasn't mounted, we need to force + * the block group descriptors out. + */ + if ((mount_flags & EXT2_MF_MOUNTED) == 0) + fs->flags &= ~EXT2_FLAG_SUPER_ONLY; + } +} + + int main (int argc, char ** argv) { @@ -126,7 +248,6 @@ int main (int argc, char ** argv) struct passwd * pw; int open_flag = 0; char *features_cmd = 0; - int mount_flags = 0; #ifdef ENABLE_NLS setlocale(LC_MESSAGES, ""); @@ -139,7 +260,7 @@ int main (int argc, char ** argv) if (argc && *argv) program_name = *argv; initialize_ext2_error_table(); - while ((c = getopt (argc, argv, "c:e:g:i:lm:r:s:u:C:L:M:O:U:")) != EOF) + while ((c = getopt (argc, argv, "c:e:g:i:j:lm:r:s:u:C:L:M:O:U:")) != EOF) switch (c) { case 'c': @@ -235,6 +356,10 @@ int main (int argc, char ** argv) case 'l': l_flag = 1; break; + case 'j': + journal_opts = optarg; + open_flag = EXT2_FLAG_RW; + break; case 'L': new_label = optarg; L_flag = 1; @@ -324,6 +449,8 @@ int main (int argc, char ** argv) return; } sb = fs->super; + /* Normally we only need to write out the superblock */ + fs->flags |= EXT2_FLAG_SUPER_ONLY; if (c_flag) { sb->s_max_mnt_count = max_mount_count; @@ -419,49 +546,16 @@ int main (int argc, char ** argv) sizeof(sb->s_last_mounted)); ext2fs_mark_super_dirty(fs); } - if (features_cmd) { - int sparse, old_sparse, filetype, old_filetype; - int journal, old_journal; - - old_sparse = sb->s_feature_ro_compat & - EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; - old_filetype = sb->s_feature_incompat & - EXT2_FEATURE_INCOMPAT_FILETYPE; - old_journal = sb->s_feature_compat & - EXT3_FEATURE_COMPAT_HAS_JOURNAL; - if (e2p_edit_feature(features_cmd, - &sb->s_feature_compat, - ok_features)) { - fprintf(stderr, _("Invalid filesystem option set: %s\n"), - features_cmd); - exit(1); - } - sparse = sb->s_feature_ro_compat & - EXT2_FEATURE_RO_COMPAT_SPARSE_SUPER; - filetype = sb->s_feature_incompat & - EXT2_FEATURE_INCOMPAT_FILETYPE; - journal = sb->s_feature_compat & - EXT3_FEATURE_COMPAT_HAS_JOURNAL; - if (old_journal && !journal && - (mount_flags & EXT2_MF_MOUNTED) && - !(mount_flags & EXT2_MF_READONLY)) { - fprintf(stderr, - _("The HAS_JOURNAL flag may only be cleared " - "the filesystem is unmounted\n" - "or mounted read-only.\n")); - exit(1); - } - if ((sparse != old_sparse) || - (filetype != old_filetype) || - (journal != old_journal)) { - sb->s_state &= ~EXT2_VALID_FS; - printf("\n%s\n", _(please_fsck)); - } - ext2fs_mark_super_dirty(fs); - } + if (features_cmd) + update_feature_set(fs, features_cmd); + if (journal_opts) + add_journal(fs); + if (U_flag) { if (strcasecmp(new_UUID, "null") == 0) { uuid_clear(sb->s_uuid); + } else if (strcasecmp(new_UUID, "time") == 0) { + uuid_generate_time(sb->s_uuid); } else if (strcasecmp(new_UUID, "random") == 0) { uuid_generate(sb->s_uuid); } else if (uuid_parse(new_UUID, sb->s_uuid)) { diff --git a/misc/util.c b/misc/util.c new file mode 100644 index 0000000..e4e147e --- /dev/null +++ b/misc/util.c @@ -0,0 +1,198 @@ +/* + * util.c --- helper functions used by tune2fs and mke2fs + * + * Copyright 1995, 1996, 1997, 1998, 1999, 2000 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +#include +#include +#ifdef HAVE_ERRNO_H +#include +#endif +#include +#ifdef HAVE_LINUX_MAJOR_H +#include +#include +#endif + +#include "et/com_err.h" +#include "e2p/e2p.h" +#include "ext2fs/ext2fs.h" +#include "nls-enable.h" +#include "util.h" + +#ifndef HAVE_STRCASECMP +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 + +void proceed_question(void) +{ + char buf[256]; + char *short_yes = _("yY"); + + fflush(stdout); + fflush(stderr); + printf(_("Proceed anyway? (y,n) ")); + buf[0] = 0; + fgets(buf, sizeof(buf), stdin); + if (strchr(short_yes, buf[0]) == 0) + exit(1); +} + +void check_plausibility(const char *device) +{ + int val; + struct stat s; + + val = stat(device, &s); + + if(val == -1) { + fprintf(stderr, _("Could not stat %s --- %s\n"), + device, 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); + proceed_question(); + return; + } + +#ifdef HAVE_LINUX_MAJOR_H +#ifndef MAJOR +#define MAJOR(dev) ((dev)>>8) +#define MINOR(dev) ((dev) & 0xff) +#endif +#ifndef SCSI_BLK_MAJOR +#define SCSI_BLK_MAJOR(M) ((M) == SCSI_DISK_MAJOR || (M) == SCSI_CDROM_MAJOR) +#endif + 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); + proceed_question(); + } +#endif +} + +void check_mount(const char *device, int force, const char *type) +{ + errcode_t retval; + int mount_flags; + + retval = ext2fs_check_if_mounted(device, &mount_flags); + if (retval) { + com_err("ext2fs_check_if_mount", retval, + _("while determining whether %s is mounted."), + device); + return; + } + if (!(mount_flags & EXT2_MF_MOUNTED)) + return; + + fprintf(stderr, _("%s is mounted; "), device); + if (force) { + fprintf(stderr, _("mke2fs forced anyway. " + "Hope /etc/mtab is incorrect.\n")); + } else { + fprintf(stderr, _("will not make a %s here!\n"), type); + exit(1); + } +} + +void parse_journal_opts(const char *opts) +{ + char *buf, *token, *next, *p, *arg; + int len; + int journal_usage = 0; + + len = strlen(opts); + buf = malloc(len+1); + if (!buf) { + fprintf(stderr, _("Couldn't allocate memory to parse " + "journal options!\n")); + exit(1); + } + strcpy(buf, opts); + for (token = buf; token && *token; token = next) { + p = strchr(token, ','); + next = 0; + if (p) { + *p = 0; + next = p+1; + } + arg = strchr(token, '='); + if (arg) { + *arg = 0; + arg++; + } +#if 0 + printf("Journal option=%s, argument=%s\n", token, + arg ? arg : "NONE"); +#endif + if (strcmp(token, "device") == 0) { + if (!arg) { + journal_usage++; + continue; + } + journal_device = arg; + } else if (strcmp(token, "size") == 0) { + if (!arg) { + journal_usage++; + continue; + } + journal_size = strtoul(arg, &p, 0); + journal_size_check: + if (*p || (journal_size < 4 || journal_size > 100)) { + fprintf(stderr, + _("Invalid journal size parameter - %s.\n"), + arg); + journal_usage++; + continue; + } + } else if (strcmp(token, "v1_superblock") == 0) { + journal_flags |= EXT2_MKJOURNAL_V1_SUPER; + continue; + } else { + journal_size = strtoul(token, &p, 0); + if (*p) + journal_usage++; + else + goto journal_size_check; + } + } + if (journal_usage) { + fprintf(stderr, _("\nBad journal options specified.\n\n" + "Journal 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" + "\tsize=\n" + "\tdevice=\n\n" + "Journal size must be between " + "4 and 100 megabytes.\n\n" )); + exit(1); + } +} + diff --git a/misc/util.h b/misc/util.h new file mode 100644 index 0000000..bf63109 --- /dev/null +++ b/misc/util.h @@ -0,0 +1,23 @@ +/* + * util.h --- header file defining prototypes for helper functions + * used by tune2fs and mke2fs + * + * Copyright 2000 by Theodore Ts'o. + * + * %Begin-Header% + * This file may be redistributed under the terms of the GNU Public + * License. + * %End-Header% + */ + +extern int journal_size; +extern int journal_flags; +extern char *journal_device; + +#ifndef HAVE_STRCASECMP +extern int strcasecmp (char *s1, char *s2); +#endif +extern void proceed_question(void); +extern void check_plausibility(const char *device); +extern void parse_journal_opts(const char *opts); +extern void check_mount(const char *device, int force, const char *type); -- 1.8.3.1