[Ocfs2-tools-devel] [PATCH] libocfs2: Move printable feature flags to feature_string.c

Joel Becker Joel.Becker at oracle.com
Thu Jul 24 16:11:02 PDT 2008


We currently have pretty-print strings for each feature flag in
ocfs2/ocfs2.h  It's just a bunch of defines, but it was good to have the
strings defined in one place.

However, we weren't even using them correctly.  tunefs.ocfs2/query.c
used them, but debugfs.ocfs2/utils.c had its own strings.  They didn't
even match.

In the end, we have a place for this sort of thing:
libocfs2/feature_string.c.  This patch adds the entire feature<->string
mapping, including tunefs INPROG flags.  The functions
ocfs2_snprint_feature_flags() and ocfs2_snprint_tunefs_flags() have the
capability of using the strings to print out a feature set.

The strings are removed from ocfs2/ocfs2.h.  tunefs.ocfs2/query.c and
debugfs.ocfs2/utils.c are changed to use the ocfs2_snprint_*_flags()
API.

As a bonus, tunefs.ocfs2 no longer needs glib.

While were there, a bug in tunefs.ocfs2/query.c is fixed.  The print
format wasn't properly terminated, so we switch to ocfs2_malloc0() to
ensure this.

This sits atop the other patches to libocfs2/feature_string.c

Signed-off-by: Joel Becker <joel.becker at oracle.com>
---
 debugfs.ocfs2/utils.c     |  114 ++++++++++-------------
 include/ocfs2/ocfs2.h     |   17 +---
 libocfs2/feature_string.c |  224 +++++++++++++++++++++++++++++++++++++++++++++
 libocfs2/ocfs2_err.et     |    3 +
 tunefs.ocfs2/Makefile     |    3 +-
 tunefs.ocfs2/query.c      |   84 +++++++++--------
 6 files changed, 322 insertions(+), 123 deletions(-)

diff --git a/debugfs.ocfs2/utils.c b/debugfs.ocfs2/utils.c
index 5eb6e90..ff2624d 100644
--- a/debugfs.ocfs2/utils.c
+++ b/debugfs.ocfs2/utils.c
@@ -1,4 +1,6 @@
-/*
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
  * utils.c
  *
  * utility functions
@@ -27,85 +29,65 @@
 
 extern dbgfs_gbls gbls;
 
-/*
- * Tests features in a flag field and adds to a printable string.  Expects
- * the flag field named 'flag' and the string named 'str'.  Primarily for
- * readability.
- */
-#define test_feature(_flag, _flagstr) do {		\
-	typeof(flag) _f = (_flag);			\
-	if (flag & _f) {				\
-		g_string_append(str, (_flagstr));	\
-		g_string_append_c(str, ' ');		\
-		flag &= ~_f;				\
-	}						\
-} while (0)
-
 void get_incompat_flag(uint32_t flag, GString *str)
 {
-
-	test_feature(OCFS2_FEATURE_INCOMPAT_HEARTBEAT_DEV, "Heartbeat");
-	test_feature(OCFS2_FEATURE_INCOMPAT_RESIZE_INPROG, "AbortedResize");
-	test_feature(OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT, "Local");
-	test_feature(OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC, "Sparse");
-	test_feature(OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP,
-		     "ExtendedSlotMap");
-	test_feature(OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK,
-		     "UserspaceClusterStack");
-	test_feature(OCFS2_FEATURE_INCOMPAT_TUNEFS_INPROG, "AbortedTunefs");
-
-        /* test_feature() clears out known flags */
-	if (flag)
-		g_string_append(str, "Unknown ");
-
-	if (!str->len)
-		g_string_append(str, "None");
-
-	return;
+	errcode_t err;
+	char buf[PATH_MAX];
+	ocfs2_fs_options flags = {
+		.opt_incompat = flag,
+	};
+
+	*buf = '\0';
+	err = ocfs2_snprint_feature_flags(buf, PATH_MAX, &flags);
+	if (!err)
+		g_string_append(str, buf);
+	else
+		com_err(gbls.cmd, err, "while processing feature flags");
 }
 
 void get_tunefs_flag(uint32_t incompat_flag, uint16_t flag, GString *str)
 {
-	if (!(incompat_flag & OCFS2_FEATURE_INCOMPAT_TUNEFS_INPROG)) {
-		g_string_append(str, "None");
-		return;
-	}
-
-	if (flag & OCFS2_TUNEFS_INPROG_REMOVE_SLOT)
-		g_string_append(str, "RemoveSlot ");
+	errcode_t err;
+	char buf[PATH_MAX];
 
-	if (flag & ~OCFS2_TUNEFS_INPROG_REMOVE_SLOT)
-		g_string_append(str, "Unknown ");
-
-	return;
+	*buf = '\0';
+	err = ocfs2_snprint_tunefs_flags(buf, PATH_MAX, flag);
+	if (!err)
+		g_string_append(str, buf);
+	else
+		com_err(gbls.cmd, err, "while processing inprog flags");
 }
 
 void get_compat_flag(uint32_t flag, GString *str)
 {
-	test_feature(OCFS2_FEATURE_COMPAT_BACKUP_SB, "BackupSuper");
-
-        /* test_feature() clears out known flags */
-        if (flag)
-		g_string_append(str, "Unknown ");
-
-	if (!str->len)
-		g_string_append(str, "None");
-
-	return;
+	errcode_t err;
+	char buf[PATH_MAX];
+	ocfs2_fs_options flags = {
+		.opt_compat = flag,
+	};
+
+	*buf = '\0';
+	err = ocfs2_snprint_feature_flags(buf, PATH_MAX, &flags);
+	if (!err)
+		g_string_append(str, buf);
+	else
+		com_err(gbls.cmd, err, "while processing feature flags");
 }
 
 void get_rocompat_flag(uint32_t flag, GString *str)
 {
-	test_feature(OCFS2_FEATURE_RO_COMPAT_UNWRITTEN, "Unwritten");
-
-        /* test_feature() clears out known flags */
-        if (flag)
-		 g_string_append(str, "Unknown ");
-
-	if (!str->len)
-		g_string_append(str, "None");
-
-	return;
+	errcode_t err;
+	char buf[PATH_MAX];
+	ocfs2_fs_options flags = {
+		.opt_ro_compat = flag,
+	};
+
+	*buf = '\0';
+	err = ocfs2_snprint_feature_flags(buf, PATH_MAX, &flags);
+	if (!err)
+		g_string_append(str, buf);
+	else
+		com_err(gbls.cmd, err, "while processing feature flags");
 }
 
 /*
diff --git a/include/ocfs2/ocfs2.h b/include/ocfs2/ocfs2.h
index 53449bf..b7231eb 100644
--- a/include/ocfs2/ocfs2.h
+++ b/include/ocfs2/ocfs2.h
@@ -68,20 +68,6 @@
 
 #define OCFS2_LIB_ABORTED_TUNEFS_SUPP		OCFS2_TUNEFS_INPROG_REMOVE_SLOT
 
-/*
- * Printable strings for feature flags
- * These MUST be kept in sync with the flags in ocfs2_fs.h, and MUST
- * be named <flag>_STR.
- */
-#define OCFS2_FEATURE_INCOMPAT_HEARTBEAT_DEV_STR	"Heartbeat"
-#define OCFS2_FEATURE_INCOMPAT_RESIZE_INPROG_STR	"AbortedResize"
-#define OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT_STR		"Local"
-#define OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC_STR		"SparseAlloc"
-#define OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP_STR	"ExtendedSlotMap"
-#define OCFS2_FEATURE_INCOMPAT_TUNEFS_INPROG_STR	"TunefsAbort"
-#define OCFS2_FEATURE_COMPAT_BACKUP_SB_STR		"BackupSuper"
-#define OCFS2_FEATURE_RO_COMPAT_UNWRITTEN_STR		"UnwrittenExtents"
-#define OCFS2_TUNEFS_INPROG_REMOVE_SLOT_STR		"RemoveSlot"
 
 /* define OCFS2_SB for ocfs2-tools */
 #define OCFS2_SB(sb)	(sb)
@@ -632,6 +618,9 @@ enum ocfs2_feature_levels {
 	OCFS2_FEATURE_LEVEL_MAX_FEATURES,
 };
 
+errcode_t ocfs2_snprint_feature_flags(char *str, size_t size,
+				      ocfs2_fs_options *flags);
+errcode_t ocfs2_snprint_tunefs_flags(char *str, size_t size, uint16_t flags);
 errcode_t ocfs2_parse_feature(const char *opts,
 			      ocfs2_fs_options *feature_flags,
 			      ocfs2_fs_options *reverse_flags);
diff --git a/libocfs2/feature_string.c b/libocfs2/feature_string.c
index d7bee33..5240b95 100644
--- a/libocfs2/feature_string.c
+++ b/libocfs2/feature_string.c
@@ -36,6 +36,18 @@ struct fs_feature_flags {
 	ocfs2_fs_options ff_flags;
 };
 
+/* Printable names for feature flags */
+struct feature_name {
+	const char		*fn_name;
+	ocfs2_fs_options	fn_flag;	/* Only the bit for this
+						   feature */
+};
+
+struct tunefs_flag_name {
+	const char	*tfn_name;
+	uint16_t	tfn_flag;
+};
+
 struct feature_level_translation {
 	const char *fl_str;
 	enum ocfs2_feature_levels fl_type;
@@ -63,6 +75,7 @@ static ocfs2_fs_options feature_level_defaults[] = {
 	 OCFS2_FEATURE_RO_COMPAT_UNWRITTEN}, /* OCFS2_FEATURE_LEVEL_MAX_FEATURES */
 };
 
+/* These are the features we support in mkfs/tunefs via --fs-features */
 static struct fs_feature_flags ocfs2_supported_features[] = {
 	{
 		"local",
@@ -97,6 +110,75 @@ static struct fs_feature_flags ocfs2_supported_features[] = {
 	},
 };
 
+/*
+ * These are the printable names of all flags in s_feature_compat,
+ * s_feature_ro_compat, and s_feature_incompat.  If libocfs2 supports this
+ * feature, its printable name must be here.
+ *
+ * These MUST be kept in sync with the flags in ocfs2_fs.h.
+ */
+static struct feature_name ocfs2_feature_names[] = {
+	{
+		.fn_name = "Heartbeat",
+		.fn_flag = {0, OCFS2_FEATURE_INCOMPAT_HEARTBEAT_DEV, 0},
+	},
+	{
+		.fn_name = "AbortedResize",
+		.fn_flag = {0, OCFS2_FEATURE_INCOMPAT_RESIZE_INPROG, 0},
+	},
+	{
+		.fn_name = "Local",
+		.fn_flag = {0, OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT, 0},
+	},
+	{
+		.fn_name = "Sparse",
+		.fn_flag = {0, OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC, 0},
+	},
+	{
+		.fn_name = "ExtendedSlotMap",
+		.fn_flag = {0, OCFS2_FEATURE_INCOMPAT_EXTENDED_SLOT_MAP, 0},
+	},
+	{
+		.fn_name = "AbortedTunefs",
+		.fn_flag = {0, OCFS2_FEATURE_INCOMPAT_TUNEFS_INPROG, 0},
+	},
+	{
+		.fn_name = "UserspaceStack",
+		.fn_flag = {0, OCFS2_FEATURE_INCOMPAT_USERSPACE_STACK, 0},
+	},
+	{
+		.fn_name = "BackupSuper",
+		.fn_flag = {OCFS2_FEATURE_COMPAT_BACKUP_SB, 0, 0},
+	},
+	{
+		.fn_name = "UnwrittenExtents",
+		.fn_flag = {0, 0, OCFS2_FEATURE_RO_COMPAT_UNWRITTEN},
+	},
+	{
+		.fn_name = "InlineData",
+		.fn_flag = {0, OCFS2_FEATURE_INCOMPAT_INLINE_DATA, 0},
+	},
+	{
+		.fn_name = NULL,
+	},
+};
+
+/*
+ * The printable names of every flag in s_tunefs_flag.  If libocfs2 supports
+ * the flag, its name must be here.
+ *
+ * These MUST be kept in sync with the flags in ocfs2_fs.h.
+ */
+static struct tunefs_flag_name ocfs2_tunefs_flag_names[] = {
+	{
+		.tfn_name = "RemoveSlot",
+		.tfn_flag = OCFS2_TUNEFS_INPROG_REMOVE_SLOT,
+	},
+	{
+		.tfn_name = NULL,
+	},
+};
+
 static inline void merge_features(ocfs2_fs_options *features,
 				  ocfs2_fs_options new_features)
 {
@@ -154,6 +236,94 @@ static int feature_match(ocfs2_fs_options *a, ocfs2_fs_options *b)
 	return 0;
 }
 
+errcode_t ocfs2_snprint_feature_flags(char *str, size_t size,
+				      ocfs2_fs_options *flags)
+{
+	int i, printed;
+	char *ptr = str;
+	size_t remain = size;
+	errcode_t err = 0;
+	char *sep = " ";
+	ocfs2_fs_options found = {0, 0, 0};
+
+	for (i = 0; ocfs2_feature_names[i].fn_name; i++) {
+		if (!feature_match(flags, &ocfs2_feature_names[i].fn_flag))
+			continue;
+		merge_features(&found, ocfs2_feature_names[i].fn_flag);
+
+		printed = snprintf(ptr, remain, "%s%s",
+				   ptr == str ? "" : sep,
+				   ocfs2_feature_names[i].fn_name);
+		if (printed < 0)
+			err = OCFS2_ET_INTERNAL_FAILURE;
+		else if (printed >= remain)
+			err = OCFS2_ET_NO_SPACE;
+		if (err)
+			break;
+
+		remain -= printed;
+		ptr += printed;
+	}
+
+	if (!err) {
+		if ((found.opt_compat != flags->opt_compat) ||
+		    (found.opt_ro_compat != flags->opt_ro_compat) ||
+		    (found.opt_incompat != flags->opt_incompat)) {
+			printed = snprintf(ptr, remain, "%sUnknown",
+					   ptr == str ? "" : sep);
+			if (printed < 0)
+				err = OCFS2_ET_INTERNAL_FAILURE;
+			else if (printed >= remain)
+				err = OCFS2_ET_NO_SPACE;
+		}
+	}
+
+	return err;
+}
+
+errcode_t ocfs2_snprint_tunefs_flags(char *str, size_t size, uint16_t flags)
+{
+	int i, printed;
+	char *ptr = str;
+	size_t remain = size;
+	errcode_t err = 0;
+	char *sep = " ";
+	uint16_t found = 0;
+
+	for (i = 0; ocfs2_tunefs_flag_names[i].tfn_name; i++) {
+		if (!(flags & ocfs2_tunefs_flag_names[i].tfn_flag))
+			continue;
+		found |= ocfs2_tunefs_flag_names[i].tfn_flag;
+
+		printed = snprintf(ptr, remain, "%s%s",
+				   ptr == str ? "" : sep,
+				   ocfs2_tunefs_flag_names[i].tfn_name);
+		if (printed < 0)
+			err = OCFS2_ET_INTERNAL_FAILURE;
+		else if (printed >= remain)
+			err = OCFS2_ET_NO_SPACE;
+		if (err)
+			break;
+
+		remain -= printed;
+		ptr += printed;
+	}
+
+	if (!err) {
+		if (found != flags) {
+			printed = snprintf(ptr, remain, "%sUnknown",
+					   ptr == str ? "" : sep);
+			if (printed < 0)
+				err = OCFS2_ET_INTERNAL_FAILURE;
+			else if (printed >= remain)
+				err = OCFS2_ET_NO_SPACE;
+		}
+	}
+
+	return err;
+}
+
+
 /*
  * If we are asked to clear a feature, we also need to clear any other
  * features that depend on it.
@@ -373,6 +543,57 @@ static void print_features(char *desc, ocfs2_fs_options *feature_set)
 	fprintf(stdout, "\n");
 }
 
+static void printable_mkfs(ocfs2_fs_options *feature_set)
+{
+	errcode_t err;
+	char buf[PATH_MAX];
+	ocfs2_fs_options flags;
+
+	fprintf(stdout, "Printable version of mkfs features:\n");
+
+	memset(&flags, 0, sizeof(flags));
+	flags.opt_compat = feature_set->opt_compat;
+	err = ocfs2_snprint_feature_flags(buf, PATH_MAX, &flags);
+	if (err)
+		snprintf(buf, PATH_MAX, "An error occurred: %s",
+			 error_message(err));
+	fprintf(stdout, "COMPAT:\t\t%s\n", buf);
+
+	memset(&flags, 0, sizeof(flags));
+	flags.opt_ro_compat = feature_set->opt_ro_compat;
+	err = ocfs2_snprint_feature_flags(buf, PATH_MAX, &flags);
+	if (err)
+		snprintf(buf, PATH_MAX, "An error occurred: %s",
+			 error_message(err));
+	fprintf(stdout, "RO_COMPAT:\t%s\n", buf);
+
+	memset(&flags, 0, sizeof(flags));
+	flags.opt_incompat = feature_set->opt_incompat;
+	err = ocfs2_snprint_feature_flags(buf, PATH_MAX, &flags);
+	if (err)
+		snprintf(buf, PATH_MAX, "An error occurred: %s",
+			 error_message(err));
+	fprintf(stdout, "INCOMPAT:\t%s\n", buf);
+
+	fprintf(stdout, "\n");
+}
+
+static void print_tunefs_flags(void)
+{
+	errcode_t err;
+	char buf[PATH_MAX];
+
+	fprintf(stdout, "Printable s_tunefs_flag:\n");
+
+	err = ocfs2_snprint_tunefs_flags(buf, PATH_MAX,
+					 OCFS2_TUNEFS_INPROG_REMOVE_SLOT);
+	if (err)
+		snprintf(buf, PATH_MAX, "An error occurred: %s",
+			 error_message(err));
+	fprintf(stdout, "FLAGS:\t\t%s\n", buf);
+	fprintf(stdout, "\n");
+}
+
 static int p_feature(ocfs2_fs_options *feature_set, void *user_data)
 {
 	int i;
@@ -463,6 +684,7 @@ int main(int argc, char *argv[])
 	print_features("\nmkfs.ocfs2 would set these features",
 		       &mkfs_features);
 	print_order(0, &mkfs_features);
+	printable_mkfs(&mkfs_features);
 	print_features("tunefs.ocfs2 would set these features",
 		       &set_features);
 	print_order(0, &set_features);
@@ -470,6 +692,8 @@ int main(int argc, char *argv[])
 		       &clear_features);
 	print_order(1, &clear_features);
 
+	print_tunefs_flags();
+
 	return 0;
 }
 
diff --git a/libocfs2/ocfs2_err.et b/libocfs2/ocfs2_err.et
index 9b33a3b..8016b3d 100644
--- a/libocfs2/ocfs2_err.et
+++ b/libocfs2/ocfs2_err.et
@@ -171,4 +171,7 @@ ec	OCFS2_ET_NO_BACKUP_SUPER,
 ec      OCFS2_ET_TOO_MANY_SLOTS,
         "Too many slots for slot map"
 
+ec	OCFS2_ET_UNKNOWN_FEATURE,
+	"Unknown feature"
+
 	end
diff --git a/tunefs.ocfs2/Makefile b/tunefs.ocfs2/Makefile
index 8333971..ab1ac8c 100644
--- a/tunefs.ocfs2/Makefile
+++ b/tunefs.ocfs2/Makefile
@@ -15,7 +15,6 @@ sbindir = $(root_sbindir)
 SBIN_PROGRAMS = tunefs.ocfs2
 
 INCLUDES = -I$(TOPDIR)/include -I.
-INCLUDES += $(GLIB_CFLAGS)
 DEFINES = -DVERSION=\"$(VERSION)\"
 
 MANS = tunefs.ocfs2.8
@@ -36,6 +35,6 @@ OBJS = $(subst .c,.o,$(CFILES))
 DIST_FILES = $(CFILES) $(HFILES) tunefs.ocfs2.8.in
 
 tunefs.ocfs2: $(OBJS) $(LIBOCFS2_DEPS) $(LIBO2DLM_DEPS) $(LIBO2CB_DEPS)
-	$(LINK) $(GLIB_LIBS) $(LIBOCFS2_LIBS) $(UUID_LIBS) $(LIBO2DLM_LIBS) $(LIBO2CB_LIBS) $(COM_ERR_LIBS)
+	$(LINK) $(LIBOCFS2_LIBS) $(UUID_LIBS) $(LIBO2DLM_LIBS) $(LIBO2CB_LIBS) $(COM_ERR_LIBS)
 
 include $(TOPDIR)/Postamble.make
diff --git a/tunefs.ocfs2/query.c b/tunefs.ocfs2/query.c
index 46418eb..a220ac9 100644
--- a/tunefs.ocfs2/query.c
+++ b/tunefs.ocfs2/query.c
@@ -1,4 +1,6 @@
-/*
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
  * query.c
  *
  * ocfs2 tune utility - implements query
@@ -24,7 +26,6 @@
 
 #include <tunefs.h>
 #include <printf.h>
-#include <glib.h>
 
 /*This number is from the man page of uuid_unparse. */
 #define UUID_UNPARSE_LEN	36
@@ -40,44 +41,49 @@ extern ocfs2_tune_opts opts;
 		} \
 	} while (0)
 
-static void tunefs_inprog_flag_in_str(uint32_t flag, GString *str)
+static void tunefs_inprog_flag_in_str(uint32_t flag, char *buf, size_t len)
 {
-	prepend_flgstr(flag, OCFS2_TUNEFS_INPROG_REMOVE_SLOT, str, " ");
+	errcode_t err;
 
-	if (flag & ~(OCFS2_TUNEFS_INPROG_REMOVE_SLOT))
-		g_string_prepend(str, "Unknown ");
+	err = ocfs2_snprint_tunefs_flags(buf, len, flag);
+	if (err)
+		com_err(opts.progname, err, "while processing inprog flags");
 }
 
-static void incompat_flag_in_str(uint32_t flag, GString *str)
+static void incompat_flag_in_str(uint32_t flag, char *buf, size_t len)
 {
-	prepend_flgstr(flag, OCFS2_FEATURE_INCOMPAT_HEARTBEAT_DEV, str, " ");
-	prepend_flgstr(flag, OCFS2_FEATURE_INCOMPAT_RESIZE_INPROG, str, " ");
-	prepend_flgstr(flag, OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT, str, " ");
-	prepend_flgstr(flag, OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC, str, " ");
-
-	if (flag & ~(OCFS2_FEATURE_INCOMPAT_HEARTBEAT_DEV |
-		     OCFS2_FEATURE_INCOMPAT_RESIZE_INPROG |
-		     OCFS2_FEATURE_INCOMPAT_LOCAL_MOUNT |
-		     OCFS2_FEATURE_INCOMPAT_SPARSE_ALLOC |
-		     OCFS2_FEATURE_INCOMPAT_TUNEFS_INPROG)) {
-		g_string_prepend(str, "Unknown ");
-	}
+	errcode_t err;
+	ocfs2_fs_options flags = {
+		.opt_incompat = flag,
+	};
+
+	err = ocfs2_snprint_feature_flags(buf, len, &flags);
+	if (err)
+		com_err(opts.progname, err, "while processing feature flags");
 }
 
-static void compat_flag_in_str(uint32_t flag, GString *str)
+static void compat_flag_in_str(uint32_t flag, char *buf, size_t len)
 {
-	prepend_flgstr(flag, OCFS2_FEATURE_COMPAT_BACKUP_SB, str, " ");
-
-	if (flag & ~(OCFS2_FEATURE_COMPAT_BACKUP_SB))
-		g_string_prepend(str, "Unknown ");
+	errcode_t err;
+	ocfs2_fs_options flags = {
+		.opt_compat = flag,
+	};
+
+	err = ocfs2_snprint_feature_flags(buf, len, &flags);
+	if (err)
+		com_err(opts.progname, err, "while processing feature flags");
 }
 
-static void ro_compat_flag_in_str(uint32_t flag, GString *str)
+static void ro_compat_flag_in_str(uint32_t flag, char *buf, size_t len)
 {
-	prepend_flgstr(flag, OCFS2_FEATURE_RO_COMPAT_UNWRITTEN, str, " ");
-
-	if (flag & ~(OCFS2_FEATURE_RO_COMPAT_UNWRITTEN))
-		g_string_prepend(str, "Unknown ");
+	errcode_t err;
+	ocfs2_fs_options flags = {
+		.opt_ro_compat = flag,
+	};
+
+	err = ocfs2_snprint_feature_flags(buf, len, &flags);
+	if (err)
+		com_err(opts.progname, err, "while processing feature flags");
 }
 
 static int print_ulong(FILE *stream, const struct printf_info *info,
@@ -175,19 +181,16 @@ static int handle_uuid(FILE *stream, const struct printf_info *info,
 
 static int handle_flag(FILE *stream, const struct printf_info *info,
 		       const void *const *args, uint32_t flag,
-		       void(*flag_func)(uint32_t flag, GString *str))
+		       void(*flag_func)(uint32_t flag, char *buf, size_t len))
 {
-	GString *str = NULL;
+	char buf[PATH_MAX]; /* Should be big enough */
 	int len = 0;
 
-	str = g_string_new(NULL);
-
-	(flag_func)(flag, str);
-
-	if (str->len)
-		len = print_string(stream, info, args, str->str);
+	*buf = '\0';
+	(flag_func)(flag, buf, PATH_MAX);
 
-	g_string_free(str, 1);
+	if (*buf)
+		len = print_string(stream, info, args, buf);
 
 	return len;
 }
@@ -252,8 +255,7 @@ static char * process_escapes(char *queryfmt)
 
 	len = strlen(queryfmt);
 
-	fmt = malloc(len + 1);
-	if (!fmt)
+	if (ocfs2_malloc0(len + 1, &fmt))
 		return NULL;
 
 	for(i = 0, j = 0; i < len; ) {
@@ -330,5 +332,5 @@ void print_query(char *queryfmt)
 	register_printf_function('O', handle_ro_compat, handle_arginfo);
 
 	fprintf(stdout, fmt);
-	free(fmt);
+	ocfs2_free(&fmt);
 }
-- 
1.5.6.2


-- 

"If you are ever in doubt as to whether or not to kiss a pretty girl, 
 give her the benefit of the doubt"
                                        -Thomas Carlyle

Joel Becker
Principal Software Developer
Oracle
E-mail: joel.becker at oracle.com
Phone: (650) 506-8127



More information about the Ocfs2-tools-devel mailing list