aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Rosenberg <drosen@google.com>2020-06-10 21:18:44 -0700
committerDaniel Rosenberg <drosen@google.com>2020-06-24 21:25:34 +0000
commit4b8ccd34c90d4020a1e5da32ae2349c869d931ed (patch)
treea5b48ac544b047f58ceec8060519b6e000c4aef3
parent9b07069cc3d80275fc87065874303e0a444df891 (diff)
downloade2fsprogs-4b8ccd34c90d4020a1e5da32ae2349c869d931ed.tar.gz
ANDROID: tune2fs: Allow setting the casefold feature
This allows tune2fs to enable casefolding on an existing filesystem. At the moment, casefolding is incompatible with encryption. Signed-off-by: Daniel Rosenberg <drosen@google.com> Bug: 159836819 Test: Create fs without casefold and enable it via tune2fs Change-Id: Ic9ed63180ef28c36e083cee85ade432e4bfcc654
-rw-r--r--misc/tune2fs.8.in32
-rw-r--r--misc/tune2fs.c97
2 files changed, 122 insertions, 7 deletions
diff --git a/misc/tune2fs.8.in b/misc/tune2fs.8.in
index 74eebb6a..8b3604f4 100644
--- a/misc/tune2fs.8.in
+++ b/misc/tune2fs.8.in
@@ -218,6 +218,33 @@ directories. Valid algorithms accepted are:
and
.IR tea .
.TP
+.BI encoding= encoding-name
+Enable the
+.I casefold
+feature in the super block and set
+.I encoding-name
+as the encoding to be used. If
+.I encoding-name
+is not specified, utf8 is used. The encoding cannot be altered if casefold
+was previously enabled.
+.TP
+.BI encoding_flags= encoding-flags
+Override the flags for filename encoding. This option may only be specified
+when
+.I encoding-name
+is also specified and when the file system doesn't already have the
+.I casefold
+feature enabled. Currently the only recognized flag is
+.I strict
+which means that invalid filenames are rejected by the file system. By default,
+.I strict
+is not enabled.
+Flags may be prefixed with "no" to explicitly leave them disabled, e.g.
+.I nostrict
+to explicitly leave the
+.I strict
+flag disabled.
+.TP
.BI mount_opts= mount_option_string
Set a set of default mount options which will be used when the file
system is mounted. Unlike the bitmask-based default mount options which
@@ -536,6 +563,11 @@ The following filesystem features can be set or cleared using
.B 64bit
Enable the file system to be larger than 2^32 blocks.
.TP
+.B casefold
+Enable support for file system level casefolding.
+.B Tune2fs
+currently only supports setting this filesystem feature.
+.TP
.B dir_index
Use hashed b-trees to speed up lookups for large directories.
.TP
diff --git a/misc/tune2fs.c b/misc/tune2fs.c
index c31c9a7c..d9aba852 100644
--- a/misc/tune2fs.c
+++ b/misc/tune2fs.c
@@ -101,6 +101,7 @@ static int rewrite_checksums;
static int feature_64bit;
static int fsck_requested;
static char *undo_file;
+static int enabling_casefold;
int journal_size, journal_flags;
char *journal_device;
@@ -160,7 +161,8 @@ static __u32 ok_features[3] = {
EXT4_FEATURE_INCOMPAT_64BIT |
EXT4_FEATURE_INCOMPAT_ENCRYPT |
EXT4_FEATURE_INCOMPAT_CSUM_SEED |
- EXT4_FEATURE_INCOMPAT_LARGEDIR,
+ EXT4_FEATURE_INCOMPAT_LARGEDIR |
+ EXT4_FEATURE_INCOMPAT_CASEFOLD,
/* R/O compat */
EXT2_FEATURE_RO_COMPAT_LARGE_FILE |
EXT4_FEATURE_RO_COMPAT_HUGE_FILE|
@@ -1415,6 +1417,23 @@ mmp_error:
EXT4_ENCRYPTION_MODE_AES_256_CTS;
}
+ if (FEATURE_ON(E2P_FEATURE_INCOMPAT, EXT4_FEATURE_INCOMPAT_CASEFOLD)) {
+ if (ext2fs_has_feature_encrypt(sb)) {
+ fputs(_("Cannot enable casefold feature on filesystems "
+ "with the encrypt feature enabled.\n"),
+ stderr);
+ return 1;
+ }
+ if (mount_flags & EXT2_MF_MOUNTED) {
+ fputs(_("The casefold feature may only be enabled when "
+ "the filesystem is unmounted.\n"), stderr);
+ return 1;
+ }
+ fs->super->s_encoding = EXT4_ENC_UTF8_12_1;
+ fs->super->s_encoding_flags = e2p_get_encoding_flags(EXT4_ENC_UTF8_12_1);
+ enabling_casefold = 1;
+ }
+
if (FEATURE_ON(E2P_FEATURE_INCOMPAT,
EXT4_FEATURE_INCOMPAT_CSUM_SEED)) {
if (!ext2fs_has_feature_metadata_csum(sb)) {
@@ -2018,9 +2037,12 @@ void do_findfs(int argc, char **argv)
static int parse_extended_opts(ext2_filsys fs, const char *opts)
{
+ struct ext2_super_block *sb = fs->super;
char *buf, *token, *next, *p, *arg;
int len, hash_alg;
int r_usage = 0;
+ int encoding = 0;
+ char *encoding_flags = NULL;
len = strlen(opts);
buf = malloc(len+1);
@@ -2073,18 +2095,18 @@ static int parse_extended_opts(ext2_filsys fs, const char *opts)
"Setting multiple mount protection update "
"interval to %lu seconds\n", intv),
intv);
- fs->super->s_mmp_update_interval = intv;
+ sb->s_mmp_update_interval = intv;
ext2fs_mark_super_dirty(fs);
} else if (!strcmp(token, "force_fsck")) {
- fs->super->s_state |= EXT2_ERROR_FS;
+ sb->s_state |= EXT2_ERROR_FS;
printf(_("Setting filesystem error flag to force fsck.\n"));
ext2fs_mark_super_dirty(fs);
} else if (!strcmp(token, "test_fs")) {
- fs->super->s_flags |= EXT2_FLAGS_TEST_FILESYS;
+ sb->s_flags |= EXT2_FLAGS_TEST_FILESYS;
printf("Setting test filesystem flag\n");
ext2fs_mark_super_dirty(fs);
} else if (!strcmp(token, "^test_fs")) {
- fs->super->s_flags &= ~EXT2_FLAGS_TEST_FILESYS;
+ sb->s_flags &= ~EXT2_FLAGS_TEST_FILESYS;
printf("Clearing test filesystem flag\n");
ext2fs_mark_super_dirty(fs);
} else if (strcmp(token, "stride") == 0) {
@@ -2130,7 +2152,7 @@ static int parse_extended_opts(ext2_filsys fs, const char *opts)
r_usage++;
continue;
}
- fs->super->s_def_hash_version = hash_alg;
+ sb->s_def_hash_version = hash_alg;
printf(_("Setting default hash algorithm "
"to %s (%d)\n"),
arg, hash_alg);
@@ -2146,9 +2168,68 @@ static int parse_extended_opts(ext2_filsys fs, const char *opts)
continue;
}
ext_mount_opts = strdup(arg);
+ } else if (!strcmp(token, "encoding")) {
+ if (!arg) {
+ r_usage++;
+ continue;
+ }
+ if (ext2fs_has_feature_encrypt(sb)) {
+ fprintf(stderr, _("error: Cannot enable casefolding if encryption is set\n"));
+ r_usage++;
+ continue;
+ }
+ if (mount_flags & EXT2_MF_MOUNTED) {
+ fputs(_("The casefold feature may only be enabled when "
+ "the filesystem is unmounted.\n"), stderr);
+ r_usage++;
+ continue;
+ }
+ if (ext2fs_has_feature_casefold(sb) && !enabling_casefold) {
+ fprintf(stderr, _("Cannot alter existing encoding\n"));
+ r_usage++;
+ continue;
+ }
+ encoding = e2p_str2encoding(arg);
+ if (encoding < 0) {
+ fprintf(stderr, _("Invalid encoding: %s\n"), arg);
+ r_usage++;
+ continue;
+ }
+ enabling_casefold = 1;
+ sb->s_encoding = encoding;
+ printf(_("Setting encoding to '%s'\n"), arg);
+ sb->s_encoding_flags =
+ e2p_get_encoding_flags(sb->s_encoding);
+ } else if (!strcmp(token, "encoding_flags")) {
+ if (!arg) {
+ r_usage++;
+ continue;
+ }
+ encoding_flags = arg;
} else
r_usage++;
}
+
+ if (encoding > 0 && !r_usage) {
+ sb->s_encoding_flags =
+ e2p_get_encoding_flags(sb->s_encoding);
+
+ if (encoding_flags &&
+ e2p_str2encoding_flags(sb->s_encoding, encoding_flags,
+ &sb->s_encoding_flags)) {
+ fprintf(stderr, _("error: Invalid encoding flag: %s\n"),
+ encoding_flags);
+ r_usage++;
+ } else if (encoding_flags)
+ printf(_("Setting encoding_flags to '%s'\n"),
+ encoding_flags);
+ ext2fs_set_feature_casefold(sb);
+ ext2fs_mark_super_dirty(fs);
+ } else if (encoding_flags && !r_usage) {
+ fprintf(stderr, _("error: An encoding must be explicitly "
+ "specified when passing encoding-flags\n"));
+ r_usage++;
+ }
if (r_usage) {
fprintf(stderr, "%s", _("\nBad options specified.\n\n"
"Extended options are separated by commas, "
@@ -2163,7 +2244,9 @@ static int parse_extended_opts(ext2_filsys fs, const char *opts)
"\tstripe_width=<RAID stride*data disks in blocks>\n"
"\tforce_fsck\n"
"\ttest_fs\n"
- "\t^test_fs\n"));
+ "\t^test_fs\n"
+ "\tencoding=<encoding>\n"
+ "\tencoding_flags=<flags>\n"));
free(buf);
return 1;
}