Whamcloud - gitweb
ChangeLog, Makefile.in, mke2fs.c, tune2fs.8.in, tune2fs.c, util.c, util.h:
authorTheodore Ts'o <tytso@mit.edu>
Wed, 3 Jan 2001 17:02:13 +0000 (17:02 +0000)
committerTheodore Ts'o <tytso@mit.edu>
Wed, 3 Jan 2001 17:02:13 +0000 (17:02 +0000)
  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
misc/Makefile.in
misc/mke2fs.c
misc/tune2fs.8.in
misc/tune2fs.c
misc/util.c [new file with mode: 0644]
misc/util.h [new file with mode: 0644]

index 3a02bd3..2ba1819 100644 (file)
@@ -1,3 +1,17 @@
+2001-01-03    <tytso@snap.thunk.org>
+
+       * 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    <tytso@snap.thunk.org>
 
        * mke2fs.c, e2image.c: Removed references to struct ext2fs_sb to
index b75d81c..10832dc 100644 (file)
@@ -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
index a6161d6..9e90c53 100644 (file)
@@ -45,21 +45,15 @@ extern int optind;
 #include <sys/types.h>
 
 #include <linux/ext2_fs.h>
-#ifdef HAVE_LINUX_MAJOR_H
-#include <linux/major.h>
-#include <sys/stat.h>          /* 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=<journal size in megabytes>\n"
-                       "\tdevice=<journal device>\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"));
index f7f7ecf..fcf1057 100644 (file)
@@ -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
index 4a61a12..adbc1a9 100644 (file)
@@ -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 (file)
index 0000000..e4e147e
--- /dev/null
@@ -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 <stdio.h>
+#include <string.h>
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#include <linux/ext2_fs.h>
+#ifdef HAVE_LINUX_MAJOR_H
+#include <linux/major.h>
+#include <sys/stat.h>
+#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=<journal size in megabytes>\n"
+                       "\tdevice=<journal device>\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 (file)
index 0000000..bf63109
--- /dev/null
@@ -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);