+/* Check if a certain feature is supported by e2fsprogs.
+ * Firstly we try to use "debugfs supported_features" command to check if
+ * the feature is supported. If this fails we try to set this feature with
+ * mke2fs to check for its support. */
+static int is_e2fsprogs_feature_supp(const char *feature)
+{
+ FILE *fp;
+ char cmd[PATH_MAX];
+ char imgname[] = "/tmp/test-img-XXXXXX";
+ int fd = -1;
+ int ret = 0;
+
+ snprintf(cmd, sizeof(cmd),
+ "debugfs -c -R \"supported_features %s\" 2>&1", feature);
+
+ /* Using popen() instead of run_command() since debugfs does not return
+ * proper error code if command is not supported */
+ fp = popen(cmd, "r");
+ if (!fp) {
+ fprintf(stderr, "%s: %s\n", progname, strerror(errno));
+ return 0;
+ }
+ ret = fread(cmd, 1, sizeof(cmd), fp);
+ if (ret > 0) {
+ if (strstr(cmd, feature) && !(strstr(cmd, "Unknown")))
+ return 0;
+ }
+
+ if ((fd = mkstemp(imgname)) < 0)
+ return -1;
+
+ snprintf(cmd, sizeof(cmd), "mke2fs -F -O %s %s 100 >/dev/null 2>&1",
+ feature, imgname);
+ /* run_command() displays the output of mke2fs when it fails for
+ * some feature, so use system() directly */
+ ret = system(cmd);
+ if (fd >= 0)
+ remove(imgname);
+
+ return ret;
+}
+
+static void disp_old_kernel_msg(char *feature)
+{
+ fprintf(stderr, "WARNING: ldiskfs filesystem does not support \"%s\" "
+ "feature.\n\n", feature);
+}
+
+static void enable_default_backfs_features(struct mkfs_opts *mop)
+{
+ struct utsname uts;
+ int maj_high, maj_low, min;
+ int ret;
+
+ strscat(mop->mo_mkfsopts, " -O dir_index", sizeof(mop->mo_mkfsopts));
+
+ if (is_e2fsprogs_feature_supp("uninit_groups") == 0)
+ strscat(mop->mo_mkfsopts, ",uninit_groups",
+ sizeof(mop->mo_mkfsopts));
+ else
+ disp_old_e2fsprogs_msg("uninit_groups", 1);
+
+ ret = uname(&uts);
+ if (ret)
+ return;
+
+ sscanf(uts.release, "%d.%d.%d", &maj_high, &maj_low, &min);
+ printf("%d %d %d\n", maj_high, maj_low, min);
+
+ /* Multiple mount protection is enabled only if failover node is
+ * specified and if kernel version is higher than 2.6.9 */
+ if (failover) {
+ if (KERNEL_VERSION(maj_high, maj_low, min) >=
+ KERNEL_VERSION(2,6,9)) {
+ if (is_e2fsprogs_feature_supp("mmp") == 0)
+ strscat(mop->mo_mkfsopts, ",mmp",
+ sizeof(mop->mo_mkfsopts));
+ else
+ disp_old_e2fsprogs_msg("mmp", 1);
+ } else {
+ disp_old_kernel_msg("mmp");
+ }
+ }
+}