[klibc] [PATCH] fstype: Fix ext4/ext4dev probing
Theodore Ts'o
tytso at mit.edu
Sat Oct 11 07:54:44 PDT 2008
Enhance fstype so it properly takes into account whether or not the
ext4 and/or ext4dev filesystems are present, and properly handles the
test_fs flag. The old code also has some really buggy checks --- for
example, where it compared the set of supported ro_compat features
against the incompat feature bitmask:
(sb->s_feature_incompat & __cpu_to_le32(EXT3_FEATURE_RO_COMPAT_SUPP)
I rewrote the ext4 checks so they are more easily understood and audited.
Signed-off-by: "Theodore Ts'o" <tytso at mit.edu>
---
usr/kinit/fstype/fstype.c | 144 ++++++++++++++++++++++++++++++++++++++++-----
1 files changed, 130 insertions(+), 14 deletions(-)
diff --git a/usr/kinit/fstype/fstype.c b/usr/kinit/fstype/fstype.c
index 95c70a8..bfd695c 100644
--- a/usr/kinit/fstype/fstype.c
+++ b/usr/kinit/fstype/fstype.c
@@ -12,11 +12,13 @@
#include <sys/types.h>
#include <stdio.h>
+#include <ctype.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <endian.h>
#include <netinet/in.h>
+#include <sys/utsname.h>
#include <sys/vfs.h>
#define cpu_to_be32(x) __cpu_to_be32(x) /* Needed by romfs_fs.h */
@@ -110,29 +112,142 @@ static int minix_image(const void *buf, unsigned long long *bytes)
return 0;
}
-static int ext4_image(const void *buf, unsigned long long *bytes)
+/*
+ * Check to see if a filesystem is in /proc/filesystems.
+ * Returns 1 if found, 0 if not
+ */
+static int fs_proc_check(const char *fs_name)
+{
+ FILE *f;
+ char buf[80], *cp, *t;
+
+ f = fopen("/proc/filesystems", "r");
+ if (!f)
+ return (0);
+ while (fgets(buf, sizeof(buf), f)) {
+ cp = buf;
+ if (!isspace(*cp)) {
+ while (*cp && !isspace(*cp))
+ cp++;
+ }
+ while (*cp && isspace(*cp))
+ cp++;
+ if ((t = strchr(cp, '\n')) != NULL)
+ *t = 0;
+ if ((t = strchr(cp, '\t')) != NULL)
+ *t = 0;
+ if ((t = strchr(cp, ' ')) != NULL)
+ *t = 0;
+ if (!strcmp(fs_name, cp)) {
+ fclose(f);
+ return (1);
+ }
+ }
+ fclose(f);
+ return (0);
+}
+
+/*
+ * Check to see if a filesystem is available as a module
+ * Returns 1 if found, 0 if not
+ */
+static int check_for_modules(const char *fs_name)
+{
+ struct utsname uts;
+ FILE *f;
+ char buf[1024], *cp, *t;
+ int i;
+
+ if (uname(&uts))
+ return (0);
+ snprintf(buf, sizeof(buf), "/lib/modules/%s/modules.dep", uts.release);
+
+ f = fopen(buf, "r");
+ if (!f)
+ return (0);
+ while (fgets(buf, sizeof(buf), f)) {
+ if ((cp = strchr(buf, ':')) != NULL)
+ *cp = 0;
+ else
+ continue;
+ if ((cp = strrchr(buf, '/')) != NULL)
+ cp++;
+ i = strlen(cp);
+ if (i > 3) {
+ t = cp + i - 3;
+ if (!strcmp(t, ".ko"))
+ *t = 0;
+ }
+ if (!strcmp(cp, fs_name)) {
+ fclose(f);
+ return (1);
+ }
+ }
+ fclose(f);
+ return (0);
+}
+
+static int base_ext4_image(const void *buf, unsigned long long *bytes,
+ int *test_fs)
{
const struct ext3_super_block *sb =
(const struct ext3_super_block *)buf;
- /* ext4dev needs ext2 + journal + test_fs flag + one !ext3 feature */
- if (sb->s_magic == __cpu_to_le16(EXT2_SUPER_MAGIC)
- && (sb->s_feature_compat
- & __cpu_to_le32(EXT3_FEATURE_COMPAT_HAS_JOURNAL))
- && (sb->s_flags & __cpu_to_le32(EXT2_FLAGS_TEST_FILESYS))
- && (sb->s_feature_incompat
- & __cpu_to_le32(EXT3_FEATURE_RO_COMPAT_SUPP)
- || sb->s_feature_incompat
- & __cpu_to_le32(EXT3_FEATURE_INCOMPAT_UNSUPPORTED)
- || sb->s_feature_incompat
- & __cpu_to_le32(EXT4_FEATURE_INCOMPAT_MMP))) {
+ if (sb->s_magic != __cpu_to_le16(EXT2_SUPER_MAGIC))
+ return 0;
+
+ /*
+ * For now, ext4 requires a journal -- but this may change
+ * soon if we get that patch from Google. :-)
+ */
+ if ((sb->s_feature_compat
+ & __cpu_to_le32(EXT3_FEATURE_COMPAT_HAS_JOURNAL)) == 0)
+ return 0;
+
+ /* There is at least one feature not supported by ext3 */
+ if ((sb->s_feature_incompat
+ & __cpu_to_le32(EXT3_FEATURE_INCOMPAT_UNSUPPORTED)) ||
+ (sb->s_feature_ro_compat
+ & __cpu_to_le32(EXT3_FEATURE_RO_COMPAT_UNSUPPORTED))) {
*bytes = (unsigned long long)__le32_to_cpu(sb->s_blocks_count)
- << (10 + __le32_to_cpu(sb->s_log_block_size));
+ << (10 + __le32_to_cpu(sb->s_log_block_size));
+ *test_fs = (sb->s_flags &
+ __cpu_to_le32(EXT2_FLAGS_TEST_FILESYS)) != 0;
return 1;
}
return 0;
}
+static int ext4_image(const void *buf, unsigned long long *bytes)
+{
+ int ret, test_fs, ext4dev_present, ext4_present;
+
+ ret = base_ext4_image(buf, bytes, &test_fs);
+ if (ret == 0)
+ return 0;
+ ext4dev_present = (fs_proc_check("ext4dev") ||
+ check_for_modules("ext4dev"));
+ ext4_present = (fs_proc_check("ext4") || check_for_modules("ext4"));
+ if ((test_fs || !ext4_present) && ext4dev_present)
+ return 0;
+ return 1;
+}
+
+static int ext4dev_image(const void *buf, unsigned long long *bytes)
+{
+ int ret, test_fs, ext4dev_present, ext4_present;
+
+ ret = base_ext4_image(buf, bytes, &test_fs);
+ if (ret == 0)
+ return 0;
+ ext4dev_present = (fs_proc_check("ext4dev") ||
+ check_for_modules("ext4dev"));
+ ext4_present = (fs_proc_check("ext4") || check_for_modules("ext4"));
+ if ((!test_fs || !ext4dev_present) && ext4_present)
+ return 0;
+ return 1;
+}
+
static int ext3_image(const void *buf, unsigned long long *bytes)
{
const struct ext3_super_block *sb =
@@ -370,7 +485,8 @@ static struct imagetype images[] = {
{0, "romfs", romfs_image},
{0, "xfs", xfs_image},
{0, "squashfs", squashfs_image},
- {1, "ext4dev", ext4_image},
+ {1, "ext4dev", ext4dev_image},
+ {1, "ext4", ext4_image},
{1, "ext3", ext3_image},
{1, "ext2", ext2_image},
{1, "minix", minix_image},
--
1.5.6.1.205.ge2c7.dirty
More information about the klibc
mailing list