From a0c3fd5e4cdc2e0b032c9ace89d960a622069c32 Mon Sep 17 00:00:00 2001 From: Theodore Ts'o Date: Tue, 15 Oct 2002 17:43:43 -0400 Subject: [PATCH] Add support for new feature in ext2/3 filesystems; a default mount options field in the superblock. Added the tune2fs '-o' option to set this field. --- lib/e2p/ChangeLog | 8 ++++ lib/e2p/Makefile.in | 10 ++-- lib/e2p/e2p.h | 4 ++ lib/e2p/ls.c | 19 ++++++++ lib/e2p/mntopts.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++ lib/ext2fs/ChangeLog | 4 ++ lib/ext2fs/ext2_fs.h | 12 ++++- misc/ChangeLog | 6 +++ misc/tune2fs.8.in | 48 +++++++++++++++++++ misc/tune2fs.c | 39 +++++++++++++-- 10 files changed, 270 insertions(+), 11 deletions(-) create mode 100644 lib/e2p/mntopts.c diff --git a/lib/e2p/ChangeLog b/lib/e2p/ChangeLog index 79714d4..ba6c7f9 100644 --- a/lib/e2p/ChangeLog +++ b/lib/e2p/ChangeLog @@ -1,3 +1,11 @@ +2002-10-15 + + * ls.c (print_mntopts, list_super2): Print any default mount + options which the filesystem might have. + + * e2p.h, mntopts.c: New function which converts back and forth + between strings and default mount options. + 2001-09-24 Theodore Tso * Release of E2fsprogs 1.29 diff --git a/lib/e2p/Makefile.in b/lib/e2p/Makefile.in index 8d20ab1..f78223e 100644 --- a/lib/e2p/Makefile.in +++ b/lib/e2p/Makefile.in @@ -17,16 +17,16 @@ INSTALL = @INSTALL@ all:: OBJS= feature.o fgetflags.o fsetflags.o fgetversion.o fsetversion.o \ - getflags.o getversion.o hashstr.o iod.o ls.o pe.o pf.o ps.o \ - setflags.o setversion.o uuid.o + getflags.o getversion.o hashstr.o iod.o ls.o mntopts.o \ + pe.o pf.o ps.o setflags.o setversion.o uuid.o SRCS= $(srcdir)/feature.c $(srcdir)/fgetflags.c \ $(srcdir)/fsetflags.c $(srcdir)/fgetversion.c \ $(srcdir)/fsetversion.c $(srcdir)/getflags.c \ $(srcdir)/getversion.c $(srcdir)/hashstr.o $(srcdir)/iod.c \ - $(srcdir)/ls.c $(srcdir)/pe.c $(srcdir)/pf.c $(srcdir)/ps.c \ - $(srcdir)/setflags.c $(srcdir)/setversion.c \ - $(srcdir)/uuid.c + $(srcdir)/ls.c (srcdir)/mntopts.o $(srcdir)/pe.c \ + $(srcdir)/pf.c $(srcdir)/ps.c $(srcdir)/setflags.c \ + $(srcdir)/setversion.c $(srcdir)/uuid.c HFILES= e2p.h diff --git a/lib/e2p/e2p.h b/lib/e2p/e2p.h index f4e4398..d76155c 100644 --- a/lib/e2p/e2p.h +++ b/lib/e2p/e2p.h @@ -41,3 +41,7 @@ const char *e2p_uuid2str(void *uu); const char *e2p_hash2string(int num); int e2p_string2hash(char *string); + +const char *e2p_mntopt2string(int compat, unsigned int mask); +int e2p_string2mntopt(char *string, unsigned int *mask); +int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok); diff --git a/lib/e2p/ls.c b/lib/e2p/ls.c index 02388ff..c18e0ff 100644 --- a/lib/e2p/ls.c +++ b/lib/e2p/ls.c @@ -112,6 +112,24 @@ static void print_features(struct ext2_super_block * s, FILE *f) #endif } +static void print_mntopts(struct ext2_super_block * s, FILE *f) +{ +#ifdef EXT2_DYNAMIC_REV + int i, printed=0; + __u32 mask = s->s_default_mount_opts, m; + + fprintf(f, "Default mount options: "); + for (i=0,m=1; i < 32; i++, m<<=1) { + if (mask & m) { + fprintf(f, " %s", e2p_mntopt2string(i, m)); + printed++; + } + } + if (printed == 0) + fprintf(f, " (none)"); + fprintf(f, "\n"); +#endif +} #ifndef EXT2_INODE_SIZE @@ -157,6 +175,7 @@ void list_super2(struct ext2_super_block * sb, FILE *f) } else fprintf(f, " (unknown)\n"); print_features(sb, f); + print_mntopts(sb, f); fprintf(f, "Filesystem state: "); print_fs_state (f, sb->s_state); fprintf(f, "\n"); diff --git a/lib/e2p/mntopts.c b/lib/e2p/mntopts.c new file mode 100644 index 0000000..5db363e --- /dev/null +++ b/lib/e2p/mntopts.c @@ -0,0 +1,131 @@ +/* + * mountopts.c --- convert between default mount options and strings + * + * Copyright (C) 2002 Theodore Ts'o + * + * This file can be redistributed under the terms of the GNU Library General + * Public License + * + */ + +#include +#include +#include +#include +#include + +#include "e2p.h" + +struct mntopt { + unsigned int mask; + const char *string; +}; + +static struct mntopt mntopt_list[] = { + { EXT2_DEFM_DEBUG, "debug" }, + { EXT2_DEFM_BSDGROUPS, "bsdgroups" }, + { EXT2_DEFM_XATTR_USER, "user_xattr" }, + { EXT2_DEFM_ACL, "acl" }, + { EXT2_DEFM_UID16, "uid16" }, + { 0, 0 }, +}; + +const char *e2p_mntopt2string(int compat, unsigned int mask) +{ + struct mntopt *f; + static char buf[20]; + int fnum; + + for (f = mntopt_list; f->string; f++) { + if (mask == f->mask) + return f->string; + } + for (fnum = 0; mask >>= 1; fnum++); + sprintf(buf, "MNTOPT_%d", fnum); + return buf; +} + +int e2p_string2mntopt(char *string, unsigned int *mask) +{ + struct mntopt *f; + char *eptr; + int num; + + for (f = mntopt_list; f->string; f++) { + if (!strcasecmp(string, f->string)) { + *mask = f->mask; + return 0; + } + } + if (strncasecmp(string, "MNTOPT_", 8)) + return 1; + + if (string[8] == 0) + return 1; + num = strtol(string+8, &eptr, 10); + if (num > 32 || num < 0) + return 1; + if (*eptr) + return 1; + *mask = 1 << num; + return 0; +} + +static char *skip_over_blanks(char *cp) +{ + while (*cp && isspace(*cp)) + cp++; + return cp; +} + +static char *skip_over_word(char *cp) +{ + while (*cp && !isspace(*cp) && *cp != ',') + cp++; + return cp; +} + +/* + * Edit a mntopt set array as requested by the user. The ok + * parameter, if non-zero, allows the application to limit what + * mntopts the user is allowed to set or clear using this function. + */ +int e2p_edit_mntopts(const char *str, __u32 *mntopts, __u32 ok) +{ + char *cp, *buf, *next; + int neg; + unsigned int mask; + + buf = malloc(strlen(str)+1); + if (!buf) + return 1; + strcpy(buf, str); + cp = buf; + while (cp && *cp) { + neg = 0; + cp = skip_over_blanks(cp); + next = skip_over_word(cp); + if (*next == 0) + next = 0; + else + *next = 0; + switch (*cp) { + case '-': + case '^': + neg++; + case '+': + cp++; + break; + } + if (e2p_string2mntopt(cp, &mask)) + return 1; + if (ok && !(ok & mask)) + return 1; + if (neg) + *mntopts &= ~mask; + else + *mntopts |= mask; + cp = next ? next+1 : 0; + } + return 0; +} diff --git a/lib/ext2fs/ChangeLog b/lib/ext2fs/ChangeLog index 3aea116..a12a608 100644 --- a/lib/ext2fs/ChangeLog +++ b/lib/ext2fs/ChangeLog @@ -1,3 +1,7 @@ +2002-10-15 + + * ext2_fs.h: Add new field in superblock for default mount options. + 2002-10-13 Theodore Ts'o * ext2fs.h: Add #include of header files necessary for ext2fs.h to diff --git a/lib/ext2fs/ext2_fs.h b/lib/ext2fs/ext2_fs.h index f2c4ac3..56fabbf 100644 --- a/lib/ext2fs/ext2_fs.h +++ b/lib/ext2fs/ext2_fs.h @@ -438,7 +438,8 @@ struct ext2_super_block { __u8 s_def_hash_version; /* Default hash version to use */ __u8 s_reserved_char_pad; __u16 s_reserved_word_pad; - __u32 s_reserved[192]; /* Padding to the end of the block */ + __u32 s_default_mount_opts; + __u32 s_reserved[191]; /* Padding to the end of the block */ }; /* @@ -501,6 +502,15 @@ struct ext2_super_block { #define EXT2_DEF_RESGID 0 /* + * Default mount options + */ +#define EXT2_DEFM_DEBUG 0x0001 +#define EXT2_DEFM_BSDGROUPS 0x0002 +#define EXT2_DEFM_XATTR_USER 0x0004 +#define EXT2_DEFM_ACL 0x0008 +#define EXT2_DEFM_UID16 0x0010 + +/* * Structure of a directory entry */ #define EXT2_NAME_LEN 255 diff --git a/misc/ChangeLog b/misc/ChangeLog index 63351a1..038cb71 100644 --- a/misc/ChangeLog +++ b/misc/ChangeLog @@ -1,3 +1,9 @@ +2002-10-15 + + * tune2fs.8.in, tune2fs.c (update_mntopts, main): Add new option + 'o' which allows the system administrator to specify + default mount options. + 2002-10-13 Theodore Ts'o * get_device_by_label.c (read_partitions): Use a 16k buffer to diff --git a/misc/tune2fs.8.in b/misc/tune2fs.8.in index 8c98256..c146a2b 100644 --- a/misc/tune2fs.8.in +++ b/misc/tune2fs.8.in @@ -37,6 +37,11 @@ tune2fs \- adjust tunable filesystem parameters on second extended filesystems .I reserved-blocks-percentage ] [ +.B \-o +.RI [^] mount-options [,...] +] + +[ .B \-r .I reserved-blocks-count ] @@ -256,6 +261,49 @@ Set the percentage of reserved filesystem blocks. .BI \-M " last-mounted-directory" Set the last-mounted directory for the filesystem. .TP +.BR \-o " [^]\fImount-option\fR[,...]" +Set or clear the indicated default mount options in the filesystem. +Default mount options can be overriden by mount options specified +either in +.BR /etc/fstab (5) +or on the command line arguments to +.BR mount (8). +Older kernels may not support this feature; in particular, +kernels which predate 2.4.20 will almost certainly ignore the +default mount options field in the superblock. +.IP +More than one mount option can be cleared or set by separating +features with commas. Mount options prefixed with a +caret character ('^') will be cleared in the filesystem's superblock; +mount options without a prefix character or prefixed with a plus +character ('+') will be added to the filesystem. +.IP +The following mount options can be set or cleared using +.BR tune2fs : +.RS 1.2i +.TP +.B debug +Enable debugging code for this filesystem. +.TP +.B bsdgroups +Emulate BSD behaviour when creating new files: they will take the group-id +of the directory in which they were created. The standard System V behaviour +is the default, where newly created files take on the fsgid of the crrent +process, unless the directry has the setgid bit set, in which case it takes +the gid from the parent directory, and also gets the setgid bit set if it is +directory itself. +.TP +.B user_xattr +Enable user-specified extended attributes. +.TP +.B acl +Enable Posix Access Control Lists. +.TP +.B uid16 +Disables 32-bit UIDs and GIDs. This is for interoperability with +older kernels which only store and expect 16-bit values. +.RE +.TP .BR \-O " [^]\fIfeature\fR[,...]" Set or clear the indicated filesystem features (options) in the filesystem. More than one filesystem feature can be cleared or set by separating diff --git a/misc/tune2fs.c b/misc/tune2fs.c index 2ea7abb..dd9f724 100644 --- a/misc/tune2fs.c +++ b/misc/tune2fs.c @@ -66,6 +66,7 @@ static unsigned long resgid, resuid; static unsigned short errors; static int open_flag; static char *features_cmd; +static char *mntopts_cmd; int journal_size, journal_flags; char *journal_device; @@ -79,10 +80,11 @@ static void usage(void) fprintf(stderr, _("Usage: %s [-c max-mounts-count] [-e errors-behavior] " "[-g group]\n" - "\t[-i interval[d|m|w]] [-j] [-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]\n" + "\t[-i interval[d|m|w]] [-j] [-J journal-options]\n" + "\t[-l] [-s sparse-flag] [-m reserved-blocks-percent]\n" + "\t[-o [^]mount-options[,...]] [-r reserved-blocks-count]\n" + "\t[-u user] [-C mount-count] [-L volume-label] " + "[-M last-mounted-dir]\n" "\t[-O [^]feature[,...]] [-T last-check-time] [-U UUID]" " device\n"), program_name); exit (1); @@ -249,6 +251,21 @@ static void remove_journal_inode(ext2_filsys fs) } /* + * Update the default mount options + */ +static void update_mntopts(ext2_filsys fs, char *mntopts) +{ + struct ext2_super_block *sb= fs->super; + + if (e2p_edit_mntopts(mntopts, &sb->s_default_mount_opts, ~0)) { + fprintf(stderr, _("Invalid mount option set: %s\n"), + mntopts); + exit(1); + } + ext2fs_mark_super_dirty(fs); +} + +/* * Update the feature set as provided by the user. */ static void update_feature_set(ext2_filsys fs, char *features) @@ -445,7 +462,7 @@ static void parse_tune2fs_options(int argc, char **argv) struct passwd * pw; printf("tune2fs %s (%s)\n", E2FSPROGS_VERSION, E2FSPROGS_DATE); - while ((c = getopt(argc, argv, "c:e:fg:i:jlm:r:s:u:C:J:L:M:O:T:U:")) != EOF) + while ((c = getopt(argc, argv, "c:e:fg:i:jlm:o:r:s:u:C:J:L:M:O:T:U:")) != EOF) switch (c) { case 'c': @@ -577,6 +594,16 @@ static void parse_tune2fs_options(int argc, char **argv) M_flag = 1; open_flag = EXT2_FLAG_RW; break; + case 'o': + if (mntopts_cmd) { + com_err (program_name, 0, + _("-o may only be specified once")); + usage(); + } + mntopts_cmd = optarg; + open_flag = EXT2_FLAG_RW; + break; + case 'O': if (features_cmd) { com_err (program_name, 0, @@ -811,6 +838,8 @@ int main (int argc, char ** argv) sizeof(sb->s_last_mounted)); ext2fs_mark_super_dirty(fs); } + if (mntopts_cmd) + update_mntopts(fs, mntopts_cmd); if (features_cmd) update_feature_set(fs, features_cmd); if (journal_size || journal_device) -- 1.8.3.1